.NET Lambda Pass方法参数

时间:2010-05-31 02:18:36

标签: c# .net lambda

我希望我遗漏了一些明显的东西,但是我遇到了一些麻烦,它定义了一个方法,该方法接受一个方法的参数来获取传递方法的方法信息。我不想实际执行该方法。

我希望能够做到:

  busObject.SetResolverMethod<ISomeInterface>(x=>x.GetNameById);

其中GetNameById是在接口ISomeInterface上定义的方法。在这种情况下,传递签名的方法示例如下:

 MyVarA GetNameById(int id){ .... }

在上面的例子中, SetResolverMethod 的主体应该能够返回/存储字符串“GetNameById”。

传入的方法没有标准签名符合(除了它总会返回某种对象)。

目前我正在将该方法设置为字符串(即“GetNameById”),但我希望它能够进行编译时检查,因此这个问题。

2 个答案:

答案 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);
}