2016-06-15 4 views
0

Ich binde einen Ausdruck Baum zu bauen, die dieses Lambda darstellen würden:C# Gebäude eine Aktion Expression mit einem Codeblock

Action<TFrom, TTo> map = 
    (from, to) => 
    { 
     to.Property1 = (Nullable<TTo>)from.Property1; 
     to.Property2 = (Nullable<TTo>)from.Property2; 
     // ...continued for all properties 
    }; 

Im Wesentlichen Ich versuche, die Nicht-Nullable-Eigenschaften von einer Klasse in dem zur Karte Nullable<T> Eigenschaften einer anderen Klasse, die denselben Eigenschaftennamen verwenden.

Ich habe diesen (falschen) Baum in meinem Versuch geschrieben, dies zu tun:

SomeObjWithOutNullable i = new SomeObjWithOutNullable(); // Not "object".. doh 
SomeObjWithNullable j = new SomeObjWithNullable(); 

ParameterExpression p1 = Expression.Parameter(typeof(SomeObjWithOutNullable), "from"); 
ParameterExpression p2 = Expression.Parameter(typeof(SomeObjWithNullable), "to"); 

MemberExpression m1 = Expression.PropertyOrField(p1, "Property1"); 
MemberExpression m2 = Expression.PropertyOrField(p2, "Property1"); 
BinaryExpression body = Expression.Assign(m1, m2); 
LambdaExpression lambda = Expression.Lambda<Action<SomeObjWithOutNullable,SomeObjWithNullable>>(body, new[] { p1,p2 }); 

var action = lambda.Compile(); 
action(i,j); 

Diese nicht kompiliert. Ich erhalte diese Ausnahme, wenn ich versuche zu:

Delegate 'System.Action<SomeObjWithOutNullable,SomeObjWithNullable>' has some invalid arguments 
Argument 1: cannot convert from 'object' to 'SomeObjWithNullable' 
Argument 2: cannot convert from 'object' to 'SomeObjWithNullable' 

Ich weiß, ich habe noch in der Typ-Konvertierung hinzuzufügen, aber ich kann nicht scheinen, um herauszufinden, wie richtig, auch die Zuordnung zu tun.

+0

Derzeit sind die Ausdrücke, die Sie geschrieben haben, aus generieren: '(von, bis) = > new SomeObjWithOutNullable(). Property1 = new SomeObjWithNullable(). Property2; 'Das ist ziemlich weit entfernt von dem Code, von dem du denkst, dass du schreibst ... – Servy

+0

Ja, ich habe diesen Tippfehler korrigiert. Ich nehme an, die Frage bezieht sich mehr auf die Aufgabe selbst. Sobald ich diesen Teil ablegen kann, kann ich den Rest ausarbeiten. – Noahm888

+0

Sie haben die Frage überhaupt nicht bearbeitet, also haben Sie dieses Problem offenbar nicht behoben. – Servy

Antwort

0

Ok, ich fand die Lösung:

void NullPropertyConvertionAction<TSource, TTarget>(TSource source, TTarget target) 
{ 
    var sourceDictionary = typeof(TSource).GetProperties() 
     .ToDictionary(s => 
      s.Name. 
      StringComparer.InvariantCultureIgnoreCase 
     ); 
    ParameterExpression p1 = Expression.Parameter(typeof(TSource), "from"); 
    ParameterExpression p2 = Expression.Parameter(typeof(TTarget), "to"); 
    var expressionBodies = new List<BinaryExpression>(); 
    foreach (var member in typeof(TTarget).GetProperties() 
     .Where(p=> p.PropertyType.IsGenericType 
     && p.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))) 
    { 
     if (sourceDictionary.ContainsKey(member.Name)) 
     { 
      MemberExpression m1 = Expression.PropertyOrField(p1, sourceDictionary[member.Name].Name); 
      MemberExpression m2 = Expression.PropertyOrField(p2, member.Name); 
      BinaryExpression body = Expression.Assign(m2, Expression.Convert(m1, member.PropertyType)); 
      expressionBodies.Add(body); 
     } 
    } 
    BlockExpression block = Expression.Block(expressionBodies.ToArray()); 
    LambdaExpression lambda = Expression.Lambda<Action<TSource,TTarget (block, new[] { p1,p2 }); 
    Action<TSource,TTarget> action = (Action<TSource,TTarget>)lambda.Compile(); 
    action(source,target); 
} 
0

Sie haben die Typinformationen weggeworfen, wenn Sie Ihre Lambda LambdaExpression niedergeschlagenen. Der einfachste Weg, dies zu lösen wäre var zu verwenden: Alternativ

var lambda = Expression.Lambda ... 

, verwenden Sie den vollständigen richtigen Typ:

Expression<Action<TSource, TTarget>> lambda = Expression.Lambda ... 
+0

Danke für den Tipp. Ich werde es tun – Noahm888

Verwandte Themen