2016-03-30 4 views
1

Пытается создать дерево выражений, чтобы сделать объект типа объекта mapper.Объект копирования дерева выражений

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. Лямбда, похоже, не видит возвращаемого значения ...
  4. Нужно ли делать блок? или есть лучший способ?
+0

Либо возвращенная лямбда должна быть 'Func ', так что вы передаете два объекта или нужно создать 'Dest'. В настоящее время вы определяете локальную переменную для 'var2', но' var2' никогда не строится (или не передается) – Rob

+0

@Rob - я хочу получить результат Func , но компилятор считает, что его все еще действие хотя у меня есть возврат ... как мне нужно изменить код на новый до $ var2 внутри? – SledgeHammer

ответ

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 
+1

LOL ... да, это работает ... намного проще, чем я пытался это сделать. Благодарю. – SledgeHammer

+1

Я очень ценю последующие разделы по генерации, тестированию и фактическим результатам, приветствия –

Смежные вопросы