代码之家  ›  专栏  ›  技术社区  ›  Rosstified

.NET lambda传递方法参数

  •  4
  • Rosstified  · 技术社区  · 15 年前

    我希望我遗漏了一些明显的东西,但是我在定义一个方法时遇到了一些困难,该方法使用一个方法的参数来获取传递方法的方法信息。我不希望实际执行该方法。

    我想能够做到:

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

    其中getnamebyid是在接口isomeInterface上定义的方法。在这种情况下,传入签名的方法的一个示例是:

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

    在上面的示例中, SetResolver方法 的主体应该能够返回/存储字符串“getnamebyid”。

    传入的方法不符合标准签名(除非它总是返回某种类型的对象)。

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

    2 回复  |  直到 15 年前
        1
  •  2
  •   Nathan Baulch    15 年前

    它不是特别漂亮/流畅,但是如果您真的想避免传递伪参数值,那么您可以使用返回委托的表达式。

    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);
    }
    
        2
  •  2
  •   Fyodor Soikin    15 年前

    不能只传递方法本身。您可以通过将方法包装在委托中来完成,但为此,您必须 SetResolverMethod 方法定义该委托的类型(您不能这样做,因为如您所说,没有一个签名),或者在调用时显式指定该类型,这将是脏的。

    你可以做的是 SetResolver方法 采用一个lambda表达式 ISomeInterface 回报 无论什么 ,并通过方法的实际执行 无论什么 作为表达式主体的参数。像这样:

        void SetResolverMethod<T>( Expression<Func<T,object>> expr );
    
        ...
    
        SetResolverMethod<ISomeInterface>( x => x.GetNameById(0) )
    

    这个 SetResolver方法 方法不会实际执行表达式,只分析它-因此,您的方法不会实际执行。

    这就是你需要的吗?