C# 表达式树复制对象
尝试创建表达式树以执行对象映射器类型的操作C# 表达式树复制对象,c#,tree,expression,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.G
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);
Type ts=typeof(源代码);
类型td=类型(目的地);
ParameterExpression val=表达式参数(ts);
ParameterExpression ret=表达式参数(td);
PropertyInfo[]propsS=ts.GetProperties();
PropertyInfo[]propsD=td.GetProperties();
List lst=新列表();
foreach(PropertyInfo pi in propsS)
{
PropertyInfo piD=propsD.Where(x=>x.Name==pi.Name).FirstOrDefault();
如果(piD!=null)
{
MethodInfo ge=pi.getMethod();
MethodInfo se=piD.GetSetMethod();
var v1=表达式调用(val,ge);
var v2=表达式调用(ret、se、v1);
第一次增补(v2);
}
}
lst.Add(Expression.Return(Expression.Label(td)、ret));
BlockExpression block=Expression.block(
新[]{ret},
1.ToArray()
);
//Func v=Expression.Lambda(block,val).Compile();
var v=表达式λ(块,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 }
}
}
.Lambda#Lambda1(ConsoleApplication2.Source$var1){
.Block(控制台应用程序2.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());
.调用$var2.set_S5(.Call$var1.get_S5());
.Return#Label1{$var2}
}
}
你可以这样写:
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);
并对其进行测试:
var s = new Source { A = 5, B = "TEST" };
var res = lambdaExpression.Compile()(s);
生成Dest
的对象:
A 5
B TEST
返回的lambda需要是
Action
以便传递两个对象,或者需要创建Dest
并使用Func
。您当前正在为var2
定义一个局部变量,但是var2
从未构造(或传入)@Rob--我想要Func结果,但编译器认为这仍然是一个操作,即使我有一个返回。。。我需要如何将代码修改为新的$var2?哈哈。。。是的,这很有效。。。比我尝试的方式简单多了。谢谢。我真的很感谢关于生成、测试和实际结果的后续章节,干杯
A 5
B TEST