将 Expression<Action<T>> 转换为 Expression<Func<T>>

4

我有一个 Expression<Action<T>>,其中 Action 是函数调用,但函数结果未被使用。让我们考虑以下代码示例:

using System;
using System.Linq.Expressions;

namespace ConsoleApp
{
    class Program
    {
        public class MyArg
        {
            public int Data { get; set; }
        }

        public class MyExecutor
        {
            public bool Executed { get; set; }

            public int MyMethod(int simpleArg, MyArg complexArg)
            {
                int result = simpleArg + complexArg.Data;
                this.Executed = true;
                return result;
            }
        }

        static void Main(string[] args)
        {
            Expression<Action<MyExecutor>> expr = t => t.MyMethod(2, new MyArg { Data = 3 });

            var executor = new MyExecutor();
            Action<MyExecutor> action = expr.Compile();
            action(executor);
            Console.WriteLine(executor.Executed); // true
        }
    }
}

可能有许多不同的操作,带有不同数量的参数。在所有情况下,我只有这种类型的expr,它总是调用一个函数并且该函数总是返回相同的类型,在上面的示例中为int

我需要像这样的内容:

static Expression<Func<MyExecutor, int>> ToExpressionOfFunc(Expression<Action<MyExecutor>> expr)
{
    // TODO
    throw new NotImplementedException();
}

能够像这样进行调用:

    Expression<Func<MyExecutor, int>> funcExpr = ToExpressionOfFunc(expr);
    Func<MyExecutor, int> func = funcExpr.Compile();
    int result = func(executor);
    Console.WriteLine(result); // should print 5

我有一种感觉,认为这应该是可能的,但不知从何处开始。在调试中,我看到一个expr.Body.Method,它具有期望的Int32 ReturnType,但不清楚如何正确提取它到新的Expression<Func>中。


1
步骤1:编写以下两行代码 Expression<Action<MyExecutor>> expr = t => t.MyMethod(2, new MyArg { Data = 3 });Expression<Func<MyExecutor,int>> ret_expr = t => t.MyMethod(2, new MyArg { Data = 3 }); 步骤2:在调试器中查看两者之间表达式树构造的差异。 - Ben Voigt
1个回答

6

很简单,只需使用现有表达式的主体和参数创建一个新的Expression<Func<MyExecutor, int>>

static Expression<Func<MyExecutor, int>> ToExpressionOfFunc(Expression<Action<MyExecutor>> expr)
{
    return Expression.Lambda<Func<MyExecutor, int>>(expr.Body, expr.Parameters);
}

请注意,如果expr的返回类型不是int,则会抛出异常。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接