Comment utiliser Expression pour construire un type anonyme?

anonymous-types c# expression-trees linq

Question

En C 3.0, vous pouvez utiliser Expression pour créer une classe avec la syntaxe suivante:

var exp = Expression.New(typeof(MyClass));
var lambda = LambdaExpression.Lambda(exp);
object myObj = lambda.Compile().DynamicInvoke();

Mais comment utilisez-vous Expression pour créer une classe anonyme?

var exp = Expression.New(typeof(MyClass));
var lambda = LambdaExpression.Lambda(exp);
object myObj = lambda.Compile().DynamicInvoke();

Réponse acceptée

Vous êtes proche, mais vous devez savoir que les types anonymes n'ont pas de constructeur par défaut. Le code suivant imprime { Name = def, Num = 456 } :

Type anonType = new { Name = "abc", Num = 123 }.GetType();
var exp = Expression.New(
            anonType.GetConstructor(new[] { typeof(string), typeof(int) }),
            Expression.Constant("def"),
            Expression.Constant(456));
var lambda = LambdaExpression.Lambda(exp);
object myObj = lambda.Compile().DynamicInvoke();
Console.WriteLine(myObj);

Si vous n'avez pas à créer beaucoup d'instances de ce type, Activator.CreateInstance fera aussi bien l'affaire (plus rapide pour quelques instances, mais plus lent pour beaucoup). Ce code affiche { Name = ghi, Num = 789 } :

Type anonType = new { Name = "abc", Num = 123 }.GetType();
var exp = Expression.New(
            anonType.GetConstructor(new[] { typeof(string), typeof(int) }),
            Expression.Constant("def"),
            Expression.Constant(456));
var lambda = LambdaExpression.Lambda(exp);
object myObj = lambda.Compile().DynamicInvoke();
Console.WriteLine(myObj);

Réponse populaire

Comme un type anonyme n'a pas de constructeur vide par défaut, vous ne pouvez pas utiliser la surcharge Expression.New(Type) ... vous devez fournir le ConstructorInfo et les paramètres à la méthode Expression.New . Pour ce faire, vous devez pouvoir obtenir le Type ... vous devez donc créer une instance "stub" du type anonyme et l'utiliser pour obtenir le Type et le ConstructorInfo , puis transmettez les paramètres au Expression.New méthode.

Comme ça:

var exp = Expression.New(new { Name = "", Num = 0 }.GetType().GetConstructors()[0], 
                         Expression.Constant("abc", typeof(string)), 
                         Expression.Constant(123, typeof(int)));
var lambda = LambdaExpression.Lambda(exp);
object myObj = lambda.Compile().DynamicInvoke();



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