Arbres d'expression avec paramètre dynamique

.net c# c#-4.0 dynamic expression-trees

Question

Je veux convertir ceci:

Func<dynamic, object> myFunc = t => return t.Name + " " + t.Surname;

Dans un arbre d'expression.

Ce que je suis venu avec, est ceci:

Func<dynamic, object> myFunc = t => return t.Name + " " + t.Surname;

Cependant, le compilateur n'aime pas le typeof(dynamic) et je le comprends bien. dynamic n'est pas un type, c'est un object par essence.

Alors j'ai procédé pour changer le ParameterExpression :

Func<dynamic, object> myFunc = t => return t.Name + " " + t.Surname;

Le code est maintenant compilé, mais il y a un problème au moment de l'exécution.

J'essaie d'obtenir la valeur de la propriété Name de la target , ce qui peut avoir un sens si l'objet était dynamic .

Mais puisque la target est considérée de type object , l'expression exprime une erreur en me disant que le Name n'existe pas en tant que propriété.

Existe-t-il une expression permettant d'extraire une propriété dynamique?

Réponse acceptée

Pour ceux qui sont ou étaient intéressés par une solution:

ParameterExpression target = Expression.Parameter(typeof(object), "target");
ParameterExpression result = Expression.Parameter(typeof(object), "result");

CallSiteBinder getName = Binder.GetMember(
   CSharpBinderFlags.None, "Name", typeof(Program),
   new CSharpArgumentInfo[] {
       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
   }
);

CallSiteBinder getSurname= Binder.GetMember(
   CSharpBinderFlags.None, "Surname", typeof(Program),
   new CSharpArgumentInfo[] {
       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
   }
);

BlockExpression block = Expression.Block(
    new[] { result },
    Expression.Assign(
        result,
        Expression.Call(typeof(string).GetMethod("Concat", new Type[] { typeof(object[]) }),
                        Expression.NewArrayInit(typeof(object),
                             Expression.Dynamic(getName, typeof(object), target),
                             Expression.Constant(" ", typeof(object)),
                             Expression.Dynamic(getSurname, typeof(object), target)
                        )
       )
    )
);

Func<dynamic, object> myFunc = Expression.Lambda<Func<dynamic, object>>(block, target).Compile();

Voici exactement ce que je fais:

  1. Création d'un CallSiteBinder qui obtient la valeur de la propriété dynamique Name de l'objet dynamique transmis en argument
  2. Création d'un CallSiteBinder qui obtient la valeur de la propriété dynamique Surname de Surname de l'objet dynamique transmis en argument
  3. Appelé la méthode string.Concat(params object[] args) . Pour cela, je dois envoyer mes arguments sous forme de tableau d' object . Je crée le tableau avec les valeurs de getName , " " et getSurname .

J'ai utilisé la réponse suivante comme guide et référence:

«Dynamique» C # 4 dans les arbres d'expression

Avec l'approche ci-dessus, on pourrait faire quelque chose comme ceci:

ParameterExpression target = Expression.Parameter(typeof(object), "target");
ParameterExpression result = Expression.Parameter(typeof(object), "result");

CallSiteBinder getName = Binder.GetMember(
   CSharpBinderFlags.None, "Name", typeof(Program),
   new CSharpArgumentInfo[] {
       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
   }
);

CallSiteBinder getSurname= Binder.GetMember(
   CSharpBinderFlags.None, "Surname", typeof(Program),
   new CSharpArgumentInfo[] {
       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)
   }
);

BlockExpression block = Expression.Block(
    new[] { result },
    Expression.Assign(
        result,
        Expression.Call(typeof(string).GetMethod("Concat", new Type[] { typeof(object[]) }),
                        Expression.NewArrayInit(typeof(object),
                             Expression.Dynamic(getName, typeof(object), target),
                             Expression.Constant(" ", typeof(object)),
                             Expression.Dynamic(getSurname, typeof(object), target)
                        )
       )
    )
);

Func<dynamic, object> myFunc = Expression.Lambda<Func<dynamic, object>>(block, target).Compile();



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi