How to use Expression to build an Anonymous Type?

How to use Expression to build an Anonymous Type?



In C# 3.0 you can use Expression to create a class with the following syntax:


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



But how do you use Expression to create an Anonymous class?


//anonymousType = typeof(new Name="abc", Num=123);
Type anonymousType = Expression.NewAnonymousType??? <--How to do ?
var exp = Expression.New(anonymousType);
var lambda = LambdaExpression.Lambda(exp);
object myObj = lambda.Compile().DynamicInvoke();





Possible dup of: stackoverflow.com/questions/606104/…
– Kirk Woll
Sep 18 '10 at 6:20





@Flash, this is not possible, at least not directly. The compiler does a lot of "magic" for you when you create anonymous types -- it's syntactic sugar for actually declaring a genuine C# class with a bunch of properties. The compiler just does all this for you. There is no expression tree type that actually does all this for you automatically. If you look at the link I referenced, it provides a workaround. However, it uses Reflection.Emit, which is not for the feint of heart.
– Kirk Woll
Sep 18 '10 at 6:23





Kirk: The OP wants to construct an anonymous class, not create one from scratch. As long as he knows at compile time what the properties' names and types are, he can get the compiler to create the type for him and all he has to do is figure out how to instance it up.
– Gabe
Sep 18 '10 at 6:34





@Gabe, I don't agree with your interpretation of what the OP wanted, but I suppose we'll see. ;)
– Kirk Woll
Sep 18 '10 at 6:36





Kirk: Based on the OP's example of var exp = Expression.New(typeof(MyClass)); it would appear as though his notion of "create a class" is really "create an instance of an existing class". If he wanted to create a new class, it wouldn't make sense for it to be anonymous.
– Gabe
Sep 18 '10 at 6:45


var exp = Expression.New(typeof(MyClass));




3 Answers
3



You're close, but you have to be aware that anonymous types don't have default constructors. The following code prints Name = def, Num = 456 :


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



If you don't have to create many instances of this type, Activator.CreateInstance will do just as well (it's faster for a few instances, but slower for many). This code prints Name = ghi, Num = 789 :


Activator.CreateInstance


Name = ghi, Num = 789


Type anonType = new Name = "abc", Num = 123 .GetType();
object myObj = Activator.CreateInstance(anonType, "ghi", 789);
Console.WriteLine(myObj);





But, Type anonType = new Name = "abc", Num = 123 .GetType(); <--It is static code,not be dynamic code.
– Flash
Sep 18 '10 at 7:54





@Flash: If you are under the impression that the C# code new Name = "abc", Num = 123 , when used in a LINQ expression, creates a new type at run-time, then you are mistaken. The compiler creates the type at compile-time, and the generated Expression Tree is indistinguishable from one that uses a non-anonymous type.
– Timwi
Sep 18 '10 at 8:28


new Name = "abc", Num = 123





Flash: You want dynamic anonymous types? What do you intend to do with them?
– Gabe
Sep 18 '10 at 12:24





I personally prefer to use Type anonType = new Name = default(string), Num = default(int) .GetType(); when defining the anonymous type as I find it makes it clearer to separate the definition from the use.
– Lukazoid
Feb 14 '12 at 12:14


Type anonType = new Name = default(string), Num = default(int) .GetType();





Usually, you would make method containing this code generic, so that one of it's paramters of type T would be anonymous object. You could then use typeof(T).GetType() instead of inlining new ... in method body.
– ghord
May 18 '13 at 16:17



typeof(T).GetType()


new ...



Since an anonymous type doesn't have a default empty constructor, you cannot use the Expression.New(Type) overload ... you have to provide the ConstructorInfo and parameters to the Expression.New method. To do that, you have to be able to get the Type ... so you need to make a "stub" instance of the anonymous type, and use that to get the Type, and the ConstructorInfo, and then pass the parameters to the Expression.New method.


Expression.New(Type)


ConstructorInfo


Expression.New


Type


ConstructorInfo


Expression.New



Like this:


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





This is a clever solution. But usually the reason one needs to write something using expression trees (the API) is precisely because one doesn't have this info at compile-time. If one did, they would have used ordinary C# expressions in the first place.
– Kirk Woll
Sep 18 '10 at 6:33






@Kirk OPs code beg to differ. ANd there's plenty of situations where you'd know the type but still had to build an ExpressionTree. DynamicLinq-2-Sql for one
– Rune FS
Sep 18 '10 at 8:01





Just nitpicking, anonymous types have empty constructors if the anonymous type is new :)
– nawfal
Aug 19 '15 at 12:23


new



You can avoid using DynamicInvoke which is painfully slow. You could make use of type inference in C# to get your anonymous type instantiated generically. Something like:


DynamicInvoke


public static Func<object, T> AnonymousInstantiator<T>(T example)

var ctor = typeof(T).GetConstructors().First();
var paramExpr = Expression.Parameter(typeof(object));
return Expression.Lambda<Func<object, T>>
(
Expression.New
(
ctor,
ctor.GetParameters().Select
(
(x, i) => Expression.Convert
(
Expression.ArrayIndex(paramExpr, Expression.Constant(i)),
x.ParameterType
)
)
), paramExpr).Compile();



Now you can call,


var instantiator = AnonymousInstantiator(new Name = default(string), Num = default(int) );

var a1 = instantiator(new object "abc", 123 ); // strongly typed
var a2 = instantiator(new object "xyz", 789 ); // strongly typed
// etc.



You could use the AnonymousInstantiator method to generate functions to instantiate any anonymous type with any number of properties, just that you have to pass an appropriate example first. The input parameters have to be passed as an object array. If you worry boxing performance there then you have to write a custom instantiator which accepts just string and int as input parameters, but the use of such an instantiator will be a bit more limited.


AnonymousInstantiator


string


int






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)