How to Combine Expressions of dynamic Types

52 views Asked by At

I would like to see if it I possible to AndAlso two expressions of type dynamic. This sample is very simplistic compared to what I am actually doing but it gets the point across. All examples I have seen using PedicateBuilder or ExpressionBuilder require the expressions to be of type bool and are generally being used as "Where" clauses. This one is returning a new, dynamic object.

public class MyObject
{
    public string Name { get; set; }
    public string Value { get; set; }   
    public string Comment { get; set; } 
}

Expression<Func<MyObject, dynamic>> e1 = i => new { MyName = i.Name };
Expression<Func<MyObject, dynamic>> e2 = i => new { MyValue = i.Value };

I am looking to get back a combined expression of e1 && e2. Am I going about this the right way?

Update 1: I have tried this answer but it expects input as MemberInitExpression and I have NewExpression which does not contain the bindings needed

1

There are 1 answers

0
NetMage On

Given

Expression<Func<MyObject, dynamic>> e1 = i1 => new { MyName = i1.Name };
Expression<Func<MyObject, dynamic>> e2 = i2 => new { MyValue = i2.Value };

You can create a new Anonymous Type that will have both properties. I will create it manually:

var mo = new MyObject();
mo.Name = "a";
mo.Value = "1";
var make_e1_2 = new { MyName = mo.Name, MyValue = mo.Value };

Then you can extract the parameters and bodies from the e1 and e2 and use them to call the new types constructor:

// (MyObject i1)
var e1_2Parm = e1.Parameters[0];

// new { MyName = i1.Name }
var e1Body = (NewExpression)e1.Body;
// new { MyValue = i1.Value }
var e2Body = (NewExpression)e2.Body.Replace(e2.Parameters[0], e1_2Parm);

// .ctor(string MyName, string MyValue)
var e1_2Constructor = make_e1_2.GetType().GetConstructors().First();

// new { MyName = i1.Name, MyValue = i1.Value }
var e1_2Body = Expression.New(e1_2Constructor, e1Body.Arguments[0], e2Body.Arguments[0]);

// (MyObject i1) => new { MyName = i1.Name, MyValue = i1.Value }
var e1_2 = Expression.Lambda<Func<MyObject, dynamic>>(e1_2Body, e1_2Parm);

This code assumes the existence of a standard ExpressionVisitor extension that replaces any occurrence of one Expression with another as Replace(). You can write your own easily or us the EF Core ReplacingExpressionVisitor class to create one.