2012-12-07 27 views
6

Byłoby bardzo proste, jeśli są w stanie ustalić poprzez wyrażenie lambda (poniżej)Jak przypisać wartość przez wyrażenie?

//An expression tree cannot contain an assignment operator 
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName = "Tim"; 

powyżej Ten kod jest nieważny w wyniku przypisania operatora. Muszę przekazać wyrażenie lambda w celu zidentyfikowania właściwości w złożonym obiekcie, który należy ustawić. W niektórych przypadkach obiekt złożony ma listę, a zatem zduplikowane typy obiektów i nazwy, dlatego potrzebuję lambda do jawnego odniesienia się do pola w obiekcie, który ma zostać zaktualizowany.

Jestem w stanie odzyskać wartość za pomocą następujących, nie ma problemu. Ale nie jestem pewien, jak użyć tej samej logiki, aby ustawić wartość, natknąłem się na Expression.Assign i wierzę, że to może być rozwiązanie.

Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName; 
var result = FindByProperty(expression); 

public static string FindByProperty(Expression<Func<Contract, object>> propertyRefExpr) 
{ 
    ComplexObj obj = new ComplexObj(); 
    Contact myContact = new Contact(); 
    myContact.FirstName = "Allen"; 
    obj.Contacts = new List<Contact>{myContact}; 
    return propertyRefExpr.Compile().Invoke(obj); 
} 

Aktualizacja:

"przechodząc przypisanie własności sposobu jak drzewa wyrażenie ..."

stosując metodę UstawWartość z ParentTypeA, wartość nie będzie działać. (Kod poniżej)

Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[0].FirstName; 
obj.AssignNewValue(expression, firstName); 

public static void AssignNewValue(this ComplexObj obj, Expression<Func<ComplexObj, object>> expression, object value) 
{ 
    var propertyInfo = (PropertyInfo)((MemberExpression)expression.Body).Member; 
    propertyInfo.SetValue(obj, value, null); 
} 
+0

http://stackoverflow.com/questions/5780232/assign-property-with-an-expressiontree –

+0

to wygląda obiecująco Stana, dzięki – AnxiousdeV

Odpowiedz

11

skończyło się stosując następujące rozwiązania. Cheers

ComplexObj obj = new ComplexObj(); 
Expression<Func<ComplexObj, object>> expression = obj => obj.Contacts[index].FirstName; 
obj.AssignNewValue(expression, firstName); 

public static void AssignNewValue(this ComplexObj obj, Expression<Func<ComplexObj, object>> expression, object value) 
{ 
    ParameterExpression valueParameterExpression = Expression.Parameter(typeof(object)); 
    Expression targetExpression = expression.Body is UnaryExpression ? ((UnaryExpression)expression.Body).Operand : expression.Body; 

    var newValue = Expression.Parameter(expression.Body.Type); 
    var assign = Expression.Lambda<Action<ComplexObj, object>> 
       (
        Expression.Assign(targetExpression, Expression.Convert(valueParameterExpression, targetExpression.Type)), 
        expression.Parameters.Single(), 
        valueParameterExpression 
       ); 

    assign.Compile().Invoke(obj, value); 
} 
0

linkowane pytanie jest chyba „właściwa” odpowiedź, ale tylko ze względu na kompletność, ty mógłby zrobić coś bardziej jak to ... robi postępować zgodnie z „powiedzieć , nie pytaj”metodologię nieco lepiej, chociaż nie mogę powiedzieć, że jak realizacji ...

void Main() 
{ 
    Expression<Func<ComplexObj, object>> expression = 
     obj => obj.Contacts[0].SetFirstName("Tim");  
} 

public class ComplexObj 
{ 
    public ComplexObj() { Contacts = new List<SimpleObj>(); } 
    public List<SimpleObj> Contacts {get; private set;} 
} 
public class SimpleObj 
{ 
    public string FirstName {get; private set;} 
    public SimpleObj SetFirstName(string name) { this.FirstName = name; return this; } 
} 
+0

Dzięki Jer, to będzie działać, jeśli istniejąca klasa były bardziej konfigurowalny, jednak ta klasa jest bardzo duża i implementacja byłaby bardzo szczegółowa. – AnxiousdeV

+0

Tak, nie mogę powiedzieć, że jest to "dobra" alternatywa, ale byłem ciekawy, czy można sfałszować wyrażenie tak, by osiągnąć zarówno przydział, jak i "ekspresję" – JerKimball

Powiązane problemy