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

时间:2010-08-25 00:43:13

标签: c# dynamic c#-4.0 expression-trees

我正在试图找出如何将所有部分组合在一起,并希望能够从一个简单的案例开始一个具体的源代码示例。

考虑以下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)?

3 个答案:

答案 0 :(得分:54)

您可以通过将动态C#添加表达式的CallSiteBinder传递给Expression.Dynamic来创建表示动态C#添加表达式的表达式树。您可以通过在原始动态表达式上运行Reflector来发现创建Binder的代码。你的例子会是这样的:

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();

答案 1 :(得分:2)

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

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

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

如果您没有进行添加操作,则可以使用它。

有关详细信息,请参阅How to create an Expression<Func<dynamic, dynamic>> - Or is it a 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;
    }
}

答案 2 :(得分:1)

非常有趣。我想这是不可能的,因为下面的代码不能编译:

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

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

  

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