C# 4 "dynamique" dans les arbres d'expression

j'essaie de trouver comment rassembler tous les morceaux, et j'apprécierais un échantillon de code source concret pour un cas simple pour commencer.

considère le code C suivant:

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

je peux produire une fonction équivalente à l'exécution en utilisant des arbres d'expression comme suit:

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

donne maintenant la lambda suivante:

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

comment générer l'équivalent en utilisant des arbres d'expression (et, présumément, Expression.Dynamic )?

47
demandé sur Pavel Minaev 2010-08-25 04:43:13

3 réponses

vous pouvez créer une arborescence d'expressions qui représente une expression dynamique C# addition en passant le CallSiteBinder pour une expression dynamique C# addition en Expression.Dynamique. Vous pouvez découvrir le code pour créer le liant en lançant Reflector sur l'expression dynamique originale. Votre exemple serait quelque chose comme ceci:

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();
50
répondu Quartermeister 2010-08-28 17:57:58

Vous ne pouvez pas le faire parce que une arborescence d'expression "ne Peut pas contenir un fonctionnement dynamique".

ce qui suit ne sera pas compilé, à cause de l'opération+, par exemple, et vous essayez de construire un arbre d'expression qui viole cette règle:

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

si vous ne faisiez pas D'opération Add, vous pourriez vous en tirer.

Voir Comment créer une Expression> - Ou est-ce un bug? pour plus d'informations.

Edit:

C'est aussi proche que possible, en définissant ma propre méthode Add qui prend les paramètres dynamiques et renvoie un résultat dynamique.

    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;
    }
}
1
répondu Richard Hein 2017-05-23 10:32:48

très intéressant. Je suppose que c'est impossible pour la même raison que la suivante ne compile pas:

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

c'est une erreur de compilateur CS1963 (qui ne semble pas être documentée par MS):

erreur CS1963: un arbre d'expression ne peut pas contenir une opération dynamique

0
répondu Igor Zevaka 2010-08-25 01:39:22