表达式树复制对象

时间:2016-03-30 22:25:22

标签: c# tree expression

尝试创建表达式树以执行对象映射器类型。

Type ts = typeof(Source);
Type td = typeof(Dest);

ParameterExpression val = Expression.Parameter(ts);
ParameterExpression ret = Expression.Parameter(td);

PropertyInfo[] propsS = ts.GetProperties();
PropertyInfo[] propsD = td.GetProperties();

List<Expression> lst = new List<Expression>();

foreach (PropertyInfo pi in propsS)
{
    PropertyInfo piD = propsD.Where(x => x.Name == pi.Name).FirstOrDefault();

    if (piD != null)
    {
        MethodInfo ge = pi.GetGetMethod();
        MethodInfo se = piD.GetSetMethod();
        var v1 = Expression.Call(val, ge);
        var v2 = Expression.Call(ret, se, v1);
        lst.Add(v2);
    }
}

lst.Add(Expression.Return(Expression.Label(td), ret));

BlockExpression block = Expression.Block(
        new[] { ret },
        lst.ToArray()
    );

//Func<Source, Dest> v = Expression.Lambda<Func<Source, Dest>>(block, val).Compile();
var v = Expression.Lambda(block, val);

这就是我现在所拥有的......它非常接近,但是看不到我错过的东西......

v出来:

.Lambda #Lambda1<System.Action`1[ConsoleApplication2.Source]>(ConsoleApplication2.Source $var1) {
    .Block(ConsoleApplication2.Dest $var2) {
        .Call $var2.set_S1(.Call $var1.get_S1());
        .Call $var2.set_S2(.Call $var1.get_S2());
        .Call $var2.set_I1(.Call $var1.get_I1());
        .Call $var2.set_I2(.Call $var1.get_I2());
        .Call $var2.set_S3(.Call $var1.get_S3());
        .Call $var2.set_S4(.Call $var1.get_S4());
        .Call $var2.set_S5(.Call $var1.get_S5());
        .Return #Label1 { $var2 }
    }
}
  1. 我需要在某处新建$ var2吗?
  2. 有没有更好的方法来分配?
  3. lambda似乎没有看到返回值......
  4. 我需要做阻止吗?还是有更好的方法?

1 个答案:

答案 0 :(得分:4)

你可以这样写:

Type sourceType = typeof(Source);
ParameterExpression source = Expression.Parameter(sourceType);

var createModel = Expression.New(typeof(Dest));
var bindings = new List<MemberAssignment>();
foreach (var prop in sourceType.GetProperties())
{
    var v1 = Expression.Call(source, prop.GetGetMethod());
    var destinationProperty = typeof(Dest).GetProperty(prop.Name);

    bindings.Add(Expression.Bind(destinationProperty, v1));
}
var init = Expression.MemberInit(createModel, bindings);

var lambdaExpression = Expression.Lambda<Func<Source, Dest>>(init, source);

将生成以下内容:

Param_0 => new Dest() 
{
    A = Param_0.get_A(), 
    B = Param_0.get_B()
}

测试它:

var s = new Source { A = 5, B = "TEST" };
var res = lambdaExpression.Compile()(s);

产生Dest的对象:

A    5   
B    TEST