I need to create a System.Linq.Expressions.Expression
that call a dynamic object. The dynamic object can be an ExpandoObject
or any other IDynamicMetaObjectProvider
.
Consider the following test:
var myInstance = DateTime.Now;
var methodInfo = myInstance.GetType().GetMethod("ToUniversalTime");
var methodCallExpression = Expression.Call(Expression.Constant(myInstance), methodInfo);
var expression = Expression.Lambda(methodCallExpression);
Assert.AreEqual(myInstance.ToUniversalTime(), expression.Compile().DynamicInvoke());
I need to create an equivalent expression when myInstance is declared like (just as an example):
dynamic myInstance = new ExpandoObject();
myInstance.MyMethod = new Func<string>(() => "hello world");
I suppose that I need to use Expression.Dynamic
method (see MSDN). But I don't known how to use it. I have tried to search on google but the only examples that I have found use the Microsoft.CSharp.RuntimeBinder.Binder
class (see MSDN) that cannot be officially used:
This API supports the .NET Framework infrastructure and is not intended to be used directly from your code.
Using Microsoft.CSharp.RuntimeBinder.Binder
I can write the code below:
dynamic myInstance = new ExpandoObject();
myInstance.MyMethod = new Func<string>(() => "hello world");
var binder = Binder.InvokeMember(
CSharpBinderFlags.None,
"MyMethod",
null,
this.GetType(),
new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null) });
var methodCallExpression = Expression.Dynamic(binder, typeof(object), Expression.Constant(myInstance));
var expression = Expression.Lambda(methodCallExpression);
Assert.AreEqual(myInstance.MyMethod(), expression.Compile().DynamicInvoke());
It this solution correct?
You can create custom dynamic objects by using the classes in the System. Dynamic namespace. For example, you can create an ExpandoObject and specify the members of that object at run time. You can also create your own type that inherits the DynamicObject class.
In C# 4.0, a new type is introduced that is known as a dynamic type. It is used to avoid the compile-time type checking. The compiler does not check the type of the dynamic type variable at compile time, instead of this, the compiler gets the type at the run time.
In 2010, the Dynamic Type was introduced and that gave us the ability to create dynamic lambda expressions.
Here is the catch: from my understanding, there is no meaning in making a dynamic call without some kind of Binder
object.
The binder object represents the rules that are followed for dynamic name resolution:
In other words, the Binder
object represents the semantics of the calling "language", while IDynamicMetaObjectProvider
represents the semantics of the called object.
So, yes, we are not supposed to use the CSharp Binder object. That can be felt especially when some issues happen that can only be worked around by using the object's internals. However, the alternative is simply to use another, non-framework-provided, Binder
implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With