2012-12-07 18 views
6

Bunun nedeni atama operatöreİfade ile bir değer nasıl atanır? I (aşağıda) bir Lambda ifadesi yoluyla atamak mümkün olsaydı

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

Bu kod yukarıdaki geçersiz çok basit olacaktır. Ayarlanması gereken karmaşık nesnede özelliği tanımlamak için bir lambda ifadesini geçmem gerekiyor. Bazı durumlarda, karmaşık nesnenin Listesi ve bunun için yinelenen nesne türleri ve adları vardır; bu nedenle, güncellenecek nesnede alanı açıkça referans vermek için lambdaya ihtiyacım vardır.

Aşağıdakileri kullanarak değeri alıyorum, sorun değil. Ama değeri ayarlamak için aynı mantığın nasıl kullanılacağından emin değilim, Expression.Assign ile karşılaştım ve bunun çözüm olabileceğine inanıyorum.

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); 
} 

Güncelleme:

ParentTypeA ile DeğerBelirle yöntemi kullanarak

"bir ifade ağacına ... gibi bir yönteme bir özellik ataması geçen" Değer çalışmayacaktır. (Aşağıdaki kodu)

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

bu Stan'i umut verici görünüyor , teşekkürler mevcut sınıf daha özelleştirilebilir olsaydı Jer, bu çalışacak – AnxiousdeV

cevap

11

aşağıdaki çözüm kullanarak sona erdi ... biraz daha iyi "metodolojisini sormayın. Şerefe

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

ancak bağlantılı soru muhtemelen "doğru" cevabı, ama sadece bütünlük uğruna, sen daha böyle bir şey yapabileceğini ... ona "haber izleyin yapar Ben uygulaması gibi diyemeyiz rağmen,

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

sayesinde, Ancak, bu sınıf çok büyük ve uygulama çok ayrıntılı olacaktır. – AnxiousdeV

+0

Evet, bunun "iyi" bir alternatif olduğunu söyleyemem, ama ifadenin her iki ödevin yanı sıra "ifade-ness" ini de başaracak şekilde yönlendirmesi ilginçti. – JerKimball

İlgili konular