代码之家  ›  专栏  ›  技术社区  ›  Pavel Minaev

表达树中的C 4“动态”

  •  48
  • Pavel Minaev  · 技术社区  · 14 年前

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

    考虑以下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 回复  |  直到 9 年前
        1
  •  53
  •   Quartermeister    14 年前

    通过将动态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();
    
        2
  •  1
  •   Community CDub    7 年前

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

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

     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;
        }
    }
    
        3
  •  0
  •   Igor Zevaka    14 年前

    非常有趣。我想这是不可能的,因为同样的原因,以下没有编译:

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

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

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