我希望我遗漏了一些明显的东西,但是我遇到了一些麻烦,它定义了一个方法,该方法接受一个方法的参数来获取传递方法的方法信息。我不想实际执行该方法。
我希望能够做到:
busObject.SetResolverMethod<ISomeInterface>(x=>x.GetNameById);
其中GetNameById是在接口ISomeInterface上定义的方法。在这种情况下,传递签名的方法示例如下:
MyVarA GetNameById(int id){ .... }
在上面的例子中, SetResolverMethod 的主体应该能够返回/存储字符串“GetNameById”。
传入的方法没有标准签名符合(除了它总会返回某种对象)。
目前我正在将该方法设置为字符串(即“GetNameById”),但我希望它能够进行编译时检查,因此这个问题。
答案 0 :(得分:2)
没有办法只传递方法本身。您可以通过将方法包装在委托中来实现,但为此,您必须使用SetResolverMethod
方法定义该委托的类型(您不能这样做,因为,如您所说,有没有人签名),或在调用时明确指定该类型,这将是脏的。
你可以做的是让SetResolverMethod
取一个lambda表达式,取ISomeInterface
并返回任何,并用传递方法的实际执行无论参数作为该表达式的主体。像这样:
void SetResolverMethod<T>( Expression<Func<T,object>> expr );
...
SetResolverMethod<ISomeInterface>( x => x.GetNameById(0) )
SetResolverMethod
方法实际上不会执行表达式,只会对其进行分析 - 因此,您的方法实际上不会被执行。
这是你需要的吗?
答案 1 :(得分:2)
它不是特别漂亮/流畅但如果你真的想避免传递虚拟参数值,那么你可以使用一个返回委托的表达式。
SetResolverMethod<ISomeInterface>(x => new Func<int, MyVarA>(x.GetNameById));
SetResolverMethod
实现看起来像这样:
public void SetResolverMethod<T>(Expression<Func<T, Delegate>> expr)
{
var unary = (UnaryExpression) expr.Body;
var methodCall = (MethodCallExpression) unary.Operand;
var constant = (ConstantExpression) methodCall.Arguments[2];
var method = (MethodInfo) constant.Value;
Console.WriteLine(method.Name);
}
编辑:如果您愿意为每个Func<>
委托创建一组重载,可以通过在方法参数类型中包含方法参数类型来提高流畅性方法
p.SetResolverMethod<ISomeInterface, int, MyVarA>(x => x.GetNameById);
如您所见,调用者不再需要指定委托类型,因此可以节省大约8个字符。
我为0,1和2参数实现了三个重载:
public void SetResolverMethod<T, TResult>(Expression<Func<T, Func<TResult>>> expr)
{
SetResolverMethod((LambdaExpression) expr);
}
public void SetResolverMethod<T, T1, TResult>(Expression<Func<T, Func<T1, TResult>>> expr)
{
SetResolverMethod((LambdaExpression) expr);
}
public void SetResolverMethod<T, T1, T2, TResult>(Expression<Func<T, Func<T1, T2, TResult>>> expr)
{
SetResolverMethod((LambdaExpression) expr);
}
private void SetResolverMethod(LambdaExpression expr)
{
var unary = (UnaryExpression) expr.Body;
var methodCall = (MethodCallExpression) unary.Operand;
var constant = (ConstantExpression) methodCall.Arguments[2];
var method = (MethodInfo) constant.Value;
Console.WriteLine(method.Name);
}