2012-12-07 11 views
6

यह असाइनमेंट ऑपरेटर की वजह से अगर मैं एक लैम्ब्डा अभिव्यक्ति (नीचे) के माध्यम से प्रदान करने में सक्षम थे बहुत सरल हो जाएगाअभिव्यक्ति के माध्यम से मूल्य कैसे असाइन करें?

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

इस कोड को ऊपर अमान्य है। जटिल वस्तु में संपत्ति की पहचान करने के लिए मुझे एक लैम्ब्डा अभिव्यक्ति पारित करने की आवश्यकता है जिसे सेट करने की आवश्यकता है। कुछ मामलों में जटिल ऑब्जेक्ट की सूची होती है और डुप्लिकेट ऑब्जेक्ट प्रकारों और नामों के लिए, इसलिए मुझे ऑब्जेक्ट में फ़ील्ड को स्पष्ट रूप से संदर्भित करने के लिए लैम्ब्डा की आवश्यकता होती है।

मैं निम्न का उपयोग कर मूल्य पुनर्प्राप्त करने में सक्षम हूं, कोई समस्या नहीं। लेकिन मुझे यकीन नहीं है कि मूल्य निर्धारित करने के लिए इस तर्क का उपयोग कैसे करें, मैं अभिव्यक्ति में आया था। साइन इन करें और विश्वास करें कि यह समाधान हो सकता है।

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

अद्यतन:

ParentTypeA साथ setValue पद्धति का उपयोग करना "एक अभिव्यक्ति पेड़ ... के रूप में एक विधि के लिए एक संपत्ति काम गुजर", मूल्य काम नहीं करेगा। (नीचे दिए गए कोड)

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

इस स्टेन का वादा लग रही है, धन्यवाद – AnxiousdeV

उत्तर

11

मैं निम्नलिखित समाधान का उपयोग कर समाप्त हो गया। चीयर्स

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

लिंक्ड करने के लिए सवाल शायद "सही" जवाब है, लेकिन सिर्फ पूर्णता के लिए के लिए, आप कुछ इस तरह कुछ कर सकता है ... इसे का पालन "बता करता है ,, थोड़ा बेहतर कार्यप्रणाली पूछना नहीं "हालांकि मैं मैं कार्यान्वयन की तरह यह नहीं कह सकते ...

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

धन्यवाद Jer, इस मौजूदा वर्ग अधिक से अनुकूलन थे काम करेगा, हालांकि, यह वर्ग बहुत बड़ा है और कार्यान्वयन बहुत verbose होगा। – AnxiousdeV

+0

हाँ, मैं यह नहीं कह सकता कि यह एक "अच्छा" विकल्प है, लेकिन अगर मैं अभिव्यक्ति को जोड़ सकता हूं तो मैं उत्सुक था कि यह दोनों असाइनमेंट के साथ-साथ "अभिव्यक्ति-नेस" – JerKimball

संबंधित मुद्दे

 संबंधित मुद्दे