Expression to create an instance with object initializer
Solution 1
To represent object initializers in an Expression, you should use Expression.MemberInit()
:
Expression<Func<bool, MyObject>> BuildLambda() {
var createdType = typeof(MyObject);
var displayValueParam = Expression.Parameter(typeof(bool), "displayValue");
var ctor = Expression.New(createdType);
var displayValueProperty = createdType.GetProperty("DisplayValue");
var displayValueAssignment = Expression.Bind(
displayValueProperty, displayValueParam);
var memberInit = Expression.MemberInit(ctor, displayValueAssignment);
return
Expression.Lambda<Func<bool, MyObject>>(memberInit, displayValueParam);
}
To verify this actually does what you want, you can call ToString()
on the created expression. In this case, the output is as expected:
displayValue => new MyObject() {DisplayValue = displayValue}
Solution 2
Finally I found my answer:
public static Func<bool, dynamic> Creator;
static void BuildLambda() {
var expectedType = typeof(MyObject);
var displayValueParam = Expression.Parameter(typeof(bool), "displayValue");
var ctor = Expression.New(expectedType);
var local = Expression.Parameter(expectedType, "obj");
var displayValueProperty = Expression.Property(local, "DisplayValue");
var returnTarget = Expression.Label(expectedType);
var returnExpression = Expression.Return(returnTarget,local, expectedType);
var returnLabel = Expression.Label(returnTarget, Expression.Default(expectedType));
var block = Expression.Block(
new[] { local },
Expression.Assign(local, ctor),
Expression.Assign(displayValueProperty, displayValueParam),
/* I forgot to remove this line:
* Expression.Return(Expression.Label(expectedType), local, expectedType),
* and now it works.
* */
returnExpression,
returnLabel
);
Creator =
Expression.Lambda<Func<bool, dynamic>>(block, displayValueParam)
.Compile();
}
UPDATE:
While it works fine, but @svick provide a better and shorter way in his answer that is actuallt wath I was looking for: MemberInit
. Please see @svick's answer.
amiry jd
My other SO-Profile: https://stackoverflow.com/users/974276/j-amiry I am a hard-working and innovative developer with near 18 years of experience mostly based on .NET (Framework & Core) technology stack. For the last few years, alongside developing some awesome applications, I was focused on some non-coding tasks such as building up development teams, team leading, tech leading, problem solving, consulting, architecting, reviewing other's code, and mentoring. As a self-motivated fast-learner experienced code-guy, who has a proactive personality to step up to new challenges, I think I'm the man who can get the job done.
Updated on June 03, 2022Comments
-
amiry jd almost 2 years
Is there any way to create an instance of an object with object initializer with an Expression Tree? I mean create an Expression Tree to build this lambda:
// my class public class MyObject { public bool DisplayValue { get; set; } } // my lambda: var lambda = (Func<bool, MyObject>) (displayValue => new MyObject { DisplayValue = displayValue });
How can I create this lambda with an Expression Tree?
UPDATE:
I tryed myself and write following code:
public static Func<bool, dynamic> Creator; static void BuildLambda() { var expectedType = typeof(MyObject); var displayValueParam = Expression.Parameter(typeof(bool), "displayValue"); var ctor = Expression.New(expectedType); var local = Expression.Parameter(expectedType, "obj"); var displayValueProperty = Expression.Property(ctor, "DisplayValue"); var returnTarget = Expression.Label(expectedType); var returnExpression = Expression.Return(returnTarget,local, expectedType); var returnLabel = Expression.Label(returnTarget, Expression.Default(expectedType)); var block = Expression.Block( new[] { local }, Expression.Assign(local, ctor), Expression.Assign(displayValueProperty, displayValueParam), Expression.Return(Expression.Label(expectedType), local, expectedType), returnExpression, returnLabel ); Creator = Expression.Lambda<Func<bool, dynamic>>(block, displayValueParam) .Compile(); }
But it throws the following error:
Cannot jump to undefined label ''.
Can everybody help me please?
-
svick over 11 yearsIf all you want to do is to compile and execute the code, this will work well. But if you wanted to use the expression in some other way (e.g. in LINQ to SQL), this might not work well. What should work is to use
MemberInit()
, as in my answer. This way you will also get shorter, more readable code. -
amiry jd over 11 years@svick thank you too much. I want to do compile and cache the func to feture using.
-
amiry jd over 11 years@svick thank you very very very much :D what I was looking for actually is
MemberInit
. thank you again. +1 and accept -
nAviD over 3 years@svick would you please answer this question : stackoverflow.com/questions/65434500/…