Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to construct .NET Expression to invoke dynamic objects

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?

like image 596
Davide Icardi Avatar asked Apr 19 '14 20:04

Davide Icardi


People also ask

How to make dynamic object in c#?

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.

What is a dynamic method in c#?

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.

Can we use dynamic in lambda expressions?

In 2010, the Dynamic Type was introduced and that gave us the ability to create dynamic lambda expressions.


1 Answers

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:

  • Should the match be case-sensitive?
  • How should method overloads be resolved?
  • What to do if the object is a non-dynamic object?
  • What fallbacks do you use?

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.

like image 129
Jean Hominal Avatar answered Oct 02 '22 17:10

Jean Hominal