Dynamic Parameter Expression Trees

I want to convert this:

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

In the tree of expressions.

What I came up with is this:

 ParameterExpression target = ExpressionParameter(typeof(dynamic), "target"); ParameterExpression result = ExpressionParameter(typeof(object), "result"); BlockExpression block = Expression.Block( new [] { result }, Expression.Assign( result, Expression.Add( Expression.Add( Expression.Property(target, "Name"), Expression.Constant(" ", typeof(string)) ), Expression.Property(target, "Surname") ) ) ); Func<dynamic, object> myFunc = Expression.Lambda<dynamic, object>>(block, target).Compile(); 

However, the compiler does not like typeof(dynamic) , and I kind of get it. dynamic not a type, essentially << 24>.

So, I started changing ParameterExpression :

 ParameterExpression target = ExpressionParameter(typeof(object), "target"); 

Now the code compiles, but there is a problem at runtime.

I am trying to get the value of the Name of target property, which may make sense if the object was dynamic .

But since target considered to be of type object , the expression throws an error message indicating that Name does not exist as a property.

Is there an expression to retrieve a dynamic property?

+7
c # dynamic expression-trees
source share
1 answer

For those who are interested in a 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(); 

That's what I'm doing:

  • Created a CallSiteBinder that gets the value of the dynamic property Name dynamic object passed as an argument
  • A CallSiteBinder created that receives the value of the dynamic Surname property of the dynamic object passed as an argument
  • The string.Concat(params object[] args) method is string.Concat(params object[] args) . To do this, I need to send my arguments as an array of object . I am creating an array with the values getName , " " and getSurname .

As a guide and reference, I used the following answer:

C # 4 "dynamic" in expression trees

Using the above approach, you can do something like this:

 dynamic person = new ExpandoObject(); person.Name = "Matt"; person.Surname = "Smith"; object value = myFunc(person); Console.WriteLine(value); //Will print out "Matt Smith" //Internally it just calls: //string.Concat(new object[] { person.Name, " ", person.Surname }); 
+3
source share

All Articles