代码之家  ›  专栏  ›  技术社区  ›  John Sibly

从Lambda表达式获取包含参数值的对象数组

  •  1
  • John Sibly  · 技术社区  · 14 年前

    我正在编写一个传递lambda表达式的函数,我想将lambda接受的参数转换为对象数组。

    我唯一能做到这一点的方法就是借用我的代码 here ,我的函数如下所示:

    public class MyClassBase<T> where T : class 
    {
        protected void DoStuff(Expression<Action<T>> selector)
        {
            ReadOnlyCollection<Expression> methodArgumentsCollection = (selector.Body as MethodCallExpression).Arguments;
            object[] methodArguments = methodArgumentsCollection.Select(c => Expression.Lambda(c is UnaryExpression ?
                            ((UnaryExpression)c).Operand : c)
                            .Compile()
                            .DynamicInvoke())
                            .ToArray();
            // do more stuff with methodArguments
        }       
    }
    
    interface IMyInterface
    {
        void MethodSingleParam(string param1);
    }
    
    class MyClass : MyClassBase<IMyInterface>
    {
        void MakeCall()
        {
            DoStuff(x => x.MethodSingleParam("abc"));
        }
    }
    

    3 回复  |  直到 14 年前
        1
  •  1
  •   Ruben    14 年前

    DoStuff(x => x.MethodSingleParam(Math.Abs(a.SomeMethod())));
    

    你怎么处理?你需要执行 Math.Abs(a.SomeMethod()) 找出它的价值。这也表明这种类型的自省是相当脆弱的(不能保证第二次调用 a.SomeMethod() 返回相同的值)。

    但是,当传递的参数是常量(由 恒压 ),你 请确定,您不需要Compile():

    protected void DoStuff(Expression<Action<T>> selector)
    {
        ReadOnlyCollection<Expression> methodArgumentsCollection = 
                      (selector.Body as MethodCallExpression).Arguments;
        object[] methodArguments = methodArgumentsCollection.Select(c =>
                  c is ConstantExpression 
                  ? ((ConstantExpression) c).Value 
                  : ... ).ToArray();
        // do more stuff with methodArguments
    }
    

    支票 恒压 确保以下代码不会调用Compile():

    DoStuff(x => x.MethodSingleParam("abc"));
    

    正如我所说,编译在这里并不是一件真正安全的事情,因此在这种情况下,您最好返回null或抛出错误。(这就是为什么我在 ... 在这里;如果需要,可以将编译放回此处。)

        2
  •  2
  •   Jon Hanna    14 年前

    好吧,最自然的方法就是运行它。实际上,它们提供的一些便利来自于能够在我们不需要像使用方法那样明确说明所用参数的地方使用它们。

    越自然的事情越容易做,这是一门好语言的标志。显然,一个人能做得越简单越好,但这对我来说并不是过分的。

        3
  •  1
  •   Douglas    14 年前

    public class MyClassBase<T>
    {
        protected void DoStuff(params T[] arguments)
        {
            // do more stuff with arguments
        }
    }
    
    class MyClass : MyClassBase<string>
    {
        void MakeCall()
        {
            DoStuff("abc");
        }
    }