【问题标题】:Can I dynamically create an expression representing a lambda which calls a method on the input parameter?我可以动态创建一个表示 lambda 的表达式,该表达式调用输入参数的方法吗?
【发布时间】:2020-03-10 17:02:19
【问题描述】:

假设我有一个 A 类的对象。 假设我需要一个在类 A 上调用方法 M 的表达式。 这甚至可行吗?

基本上,我需要以编程方式获取此 lambda a => a.M();

诀窍是,我想通用地执行此操作,即我计划使用反射来确定该方法称为 M 以及它需要什么参数。

我尝试使用 Expression.Lambda(MethodCallExpression method, ParameterExpression params)。

问题在于,当我定义方法调用表达式时,我必须指定一个实例(如果它是静态方法,则将其保留为 null,而事实并非如此)。我不想要这个。我希望将传递给 lambda 的任何参数(在我的示例中为 a)作为实例。

这可能吗?

【问题讨论】:

    标签: c#


    【解决方案1】:

    是的,可以在运行时构造linq expression

    例如下面是构造返回object 的方法调用表达式的示例。这确实是一个虚拟示例,因为最好避免使用 object 以支持严格类型。

    static Expression<Func<T, object>> ComposeMethodCallExpressionAsFuncObject<T>(string methodName)
    {
        MethodInfo mi = typeof(T).GetMethod(methodName, types: new Type[0])
            ?? throw new ArgumentException($"There is no '{methodName}' method in the '{typeof(T).Name}' with the empty arguments list!");
    
        var paramExpression = Expression.Parameter(typeof(T));
        var methodCallExpression = Expression.Call(paramExpression, mi);
    
        var result = Expression.Lambda<Func<T, object>>(methodCallExpression, paramExpression);
        return result; // (T obj) =>obj.methodName()
    }
    

    ,以及使用示例:

    int foo = 9988;
    var expression = ComposeMethodCallExpressionAsFuncObject<int>(nameof(int.ToString));
    //expression: (int obj) => obj.ToString()
    var result = expression.Compile()(foo);
    Assert.AreEqual("9988", result);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 2011-12-13
      • 2018-02-22
      相关资源
      最近更新 更多