C# 4 "dynamic" in expression trees

C#DynamicC# 4.0Expression Trees

C# Problem Overview


I'm trying to figure out how to put all the pieces together, and would appreciate a concrete source code sample for a simple case to start with.

Consider the following C# code:

Func<int, int, int> f = (x, y) => x + y;

I can produce an equivalent function at runtime using expression trees as follows:

var x = Expression.Parameter(typeof(int), "x");
var y = Expression.Parameter(typeof(int), "y");
Func<int, int, int> f =
    Expression.Lambda<Func<int, int, int>>(
        Expression.Add(x, y),
        new[] { x, y }
    ).Compile();

Now given the following lambda:

Func<dynamic, dynamic, dynamic> f = (x, y) => x + y;

how would I generate the equivalent using expression trees (and, presumably, Expression.Dynamic)?

C# Solutions


Solution 1 - C#

You can create an expression tree that represents a dynamic C# addition expression by passing the CallSiteBinder for a dynamic C# addition expression into Expression.Dynamic. You can discover the code to create the Binder by running Reflector on the original dynamic expression. Your example would go something like this:

var x = Expression.Parameter(typeof(object), "x");
var y = Expression.Parameter(typeof(object), "y");
var binder = Binder.BinaryOperation(
    CSharpBinderFlags.None, ExpressionType.Add, typeof(Program),
    new CSharpArgumentInfo[] { 
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), 
        CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)});
Func<dynamic, dynamic, dynamic> f =
    Expression.Lambda<Func<object, object, object>>(
        Expression.Dynamic(binder, typeof(object), x, y),
        new[] { x, y }
    ).Compile();

Solution 2 - C#

You cannot do that because an expression tree "May not contain a dynamic operation".

The following will not compile, because of the + operation, for example, and you are trying to build an expression tree that violates that rule:

 Expression<Func<dynamic, dynamic, dynamic>> f = (x, y) => x + y;

If you were not doing an Add operation you could get away with it.

See https://stackoverflow.com/questions/2046480/net-4-0-how-to-create-an-expressionfuncdynamic-dynamic-or-is-it-a-bug for more information.

Edit:

This is as close as I can get, by defining my own Add method that takes dynamic parameters and returns a dynamic result.

    class Program
{
    static void Main(string[] args)
    {
    
        var x = Expression.Parameter(typeof(object), "x");
        var y = Expression.Parameter(typeof(object), "y");
         Func<dynamic, dynamic, dynamic> f =
             Expression.Lambda<Func<dynamic, dynamic, dynamic>>(
                 Expression.Call(typeof(Program), "Add", null, x, y),
                 new[] { x, y }
             ).Compile();
     
       Console.WriteLine(f(5, 2));
       Console.ReadKey();
    }

    public static dynamic Add(dynamic x, dynamic y)
    {
        return x + y;
    }
}

Solution 3 - C#

Very interesting. I guess it's impossible for the same reason the following does not compile:

Expression<Func<dynamic, dynamic, int>> func = (p1, p2) => p1 + p2;

It's a compiler error CS1963 (which doesn't seem to be documented by MS):

> error CS1963: An expression tree may not contain a dynamic operation

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPavel MinaevView Question on Stackoverflow
Solution 1 - C#QuartermeisterView Answer on Stackoverflow
Solution 2 - C#Richard Anthony Freeman-HeinView Answer on Stackoverflow
Solution 3 - C#Igor ZevakaView Answer on Stackoverflow