Créer un sélecteur d'expression Lambda pour une nouvelle classe à l'aide de l'arbre d'expression

c# c#-6.0 expression-trees lambda linq

Question

Relatif à:

Créer un arbre d'expression pour le sélecteur

Créer une expression lambda avec 3 conditions

Convert Contains To Tree Expression

Convertir List.Contains en arbre d'expression

Je veux créer une expression de Selector utilisant Expression Tree pour une nouvelle classe. Veuillez considérer ce code:

s => new Allocation
     {
         Id = s.Id,
         UnitName = s.UnitName,
         Address = s.NewAddress,
         Tel = s.NewTel
      }

J'ai grande classe ( MyClass ) que je veux sélectionner certaines de ses propriétés. Mais je veux le créer dynamiquement. Comment puis-je faire ceci?

Merci

Réponse acceptée

La solution consiste à écrire le code équivalent, puis à le décompiler. Par exemple:

using System;
using System.Linq.Expressions;

class Program
{
    static void Main()
    {
        ShowMeTheLambda<Foo, Allocation>(s => new Allocation
        {
            Id = s.Id,
            UnitName = s.UnitName,
            Address = s.NewAddress,
            Tel = s.NewTel
        });
    }
    static void ShowMeTheLambda<TFrom, TTo>(Expression<Func<TFrom, TTo>> lambda)
    { }
}
class Foo
{
    public int Id { get; set; }
    public string UnitName { get; set; }
    public string NewTel { get; set; }
    public string NewAddress { get; set; }
}
class Allocation
{
    public int Id { get; set; }
    public string UnitName { get; set; }
    public string Tel { get; set; }
    public string Address { get; set; }
}

Maintenant, si je compile ceci et le décompile avec "réflecteur", je reçois:

private static void Main()
{
    ParameterExpression expression;
    MemberBinding[] bindings = new MemberBinding[] { Expression.Bind((MethodInfo) methodof(Allocation.set_Id), Expression.Property(expression = Expression.Parameter(typeof(Foo), "s"), (MethodInfo) methodof(Foo.get_Id))), Expression.Bind((MethodInfo) methodof(Allocation.set_UnitName), Expression.Property(expression, (MethodInfo) methodof(Foo.get_UnitName))), Expression.Bind((MethodInfo) methodof(Allocation.set_Address), Expression.Property(expression, (MethodInfo) methodof(Foo.get_NewAddress))), Expression.Bind((MethodInfo) methodof(Allocation.set_Tel), Expression.Property(expression, (MethodInfo) methodof(Foo.get_NewTel))) };
    ParameterExpression[] parameters = new ParameterExpression[] { expression };
    ShowMeTheLambda<Foo, Allocation>(Expression.Lambda<Func<Foo, Allocation>>(Expression.MemberInit(Expression.New(typeof(Allocation)), bindings), parameters));

}

Note: memberof et methodof n'existent pas réellement en C # - vous pouvez obtenir manuellement la méthode infos par réflexion ou utiliser Expression.PropertyOrField . On peut donc le réécrire comme:

ParameterExpression expression = Expression.Parameter(typeof(Foo), "s");
MemberBinding[] bindings = new MemberBinding[]
{
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.Id)), Expression.PropertyOrField(expression, nameof(Foo.Id))),
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.UnitName)), Expression.PropertyOrField(expression, nameof(Foo.UnitName))),
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.Address)), Expression.PropertyOrField(expression, nameof(Foo.NewAddress))),
    Expression.Bind(typeof(Allocation).GetProperty(nameof(Allocation.Tel)), Expression.PropertyOrField(expression, nameof(Foo.NewTel))),
};
ParameterExpression[] parameters = new ParameterExpression[] { expression };
var lambda = Expression.Lambda<Func<Foo, Allocation>>(Expression.MemberInit(Expression.New(typeof(Allocation)), bindings), parameters);



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