表达式树中的C#4“动态”

我试图弄清楚如何将所有部分组合在一起,并希望从一个简单的案例开始就获得一个具体的源代码示例。

考虑以下C#代码:

Func<int, int, int> f = (x, y) => x + y;

我可以在运行时使用表达式树生成等效函数,如下所示:

var x = Expression.Parameter(typeof(int), "x");
var y = Expression.Parameter(typeof(int), "y");
Func<int, int, int> f =
    Expression.Lambda<Func<int, int, int>>(
        Expression.Add(x, y),
        new[] { x, y }
    ).Compile();

现在给出以下lambda:

Func<dynamic, dynamic, dynamic> f = (x, y) => x + y;

如何使用表达式树(以及大概Expression.Dynamic)生成等效项?

Pavel Minaev asked 2020-02-13T17:52:22Z
3个解决方案
54 votes

您可以通过将动态C#加法表达式的CallSiteBinder传递到Expression.Dynamic中来创建表示动态C#加法表达式的表达式树。 您可以通过在原始动态表达式上运行Reflector来发现创建活页夹的代码。 您的示例将如下所示:

var x = Expression.Parameter(typeof(object), "x");
var y = Expression.Parameter(typeof(object), "y");
var binder = Binder.BinaryOperation(
    CSharpBinderFlags.None, ExpressionType.Add, typeof(Program),
    new CSharpArgumentInfo[] { 
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)});
Func<dynamic, dynamic, dynamic> f =
    Expression.Lambda<Func<object, object, object>>(
        Expression.Dynamic(binder, typeof(object), x, y),
        new[] { x, y }
    ).Compile();
Quartermeister answered 2020-02-13T17:52:38Z
2 votes

您不能这样做,因为表达式树“可能不包含动态操作”。

例如,由于+操作,以下内容将无法编译,并且您正在尝试构建违反该规则的表达式树:

 Expression<Func<dynamic, dynamic, dynamic>> f = (x, y) => x + y;

如果您不执行添加操作,则可以避免。

请参见如何创建Expression <Func <dynamic,dynamic >>-还是Bug? 了解更多信息。

编辑:

通过定义我自己的Add方法,该方法采用动态参数并返回动态结果,这与我所能达到的效果非常接近。

    class Program
{
    static void Main(string[] args)
    {

        var x = Expression.Parameter(typeof(object), "x");
        var y = Expression.Parameter(typeof(object), "y");
         Func<dynamic, dynamic, dynamic> f =
             Expression.Lambda<Func<dynamic, dynamic, dynamic>>(
                 Expression.Call(typeof(Program), "Add", null, x, y),
                 new[] { x, y }
             ).Compile();

       Console.WriteLine(f(5, 2));
       Console.ReadKey();
    }

    public static dynamic Add(dynamic x, dynamic y)
    {
        return x + y;
    }
}
Richard Anthony Hein answered 2020-02-13T17:53:20Z
1 votes

很有意思。 我猜由于以下原因无法编译,这是不可能的:

Expression<Func<dynamic, dynamic, int>> func = (p1, p2) => p1 + p2;

这是一个编译器错误CS1963(MS似乎没有记录):

错误CS1963:表达式树可能不包含动态操作

Igor Zevaka answered 2020-02-13T17:53:50Z
translate from https://stackoverflow.com:/questions/3562088/c-sharp-4-dynamic-in-expression-trees