2012-03-07 15 views
45

निम्न विधि को देखते हुए:अभिव्यक्तियों का उपयोग करके संपत्ति मूल्य कैसे सेट करें?

public static void SetPropertyValue(object target, string propName, object value) 
{ 
    var propInfo = target.GetType().GetProperty(propName, 
         BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly); 

    if (propInfo == null) 
     throw new ArgumentOutOfRangeException("propName", "Property not found on target"); 
    else 
     propInfo.SetValue(target, value, null); 
} 

आप लिख यह अभिव्यक्ति लक्ष्य के लिए एक अतिरिक्त पैरामीटर में पारित करने के लिए की जरूरत के बिना सक्षम है बराबर के बारे में कैसे जाना होगा?

यह संपत्ति को सीधे स्थापित करने के बजाय क्यों करें, मैं आपको सुन सकता हूं। उदाहरण के लिए मान लीजिए कि हम एक संपत्ति एक सार्वजनिक गेटर लेकिन निजी सेटर है साथ निम्नलिखित वर्ग है:

public class Customer 
{ 
    public string Title {get; private set;} 
    public string Name {get; set;} 
} 

मैं चाहते हैं कॉल करने के लिए सक्षम होने के लिए:

var myCustomerInstance = new Customer(); 
SetPropertyValue<Customer>(cust => myCustomerInstance.Title, "Mr"); 

अब यहाँ कुछ नमूना कोड है।

public static void SetPropertyValue<T>(Expression<Func<T, Object>> memberLamda , object value) 
{ 
    MemberExpression memberSelectorExpression; 
    var selectorExpression = memberLamda.Body; 
    var castExpression = selectorExpression as UnaryExpression; 

    if (castExpression != null) 
     memberSelectorExpression = castExpression.Operand as MemberExpression; 
    else 
     memberSelectorExpression = memberLamda.Body as MemberExpression; 

    // How do I get the value of myCustomerInstance so that I can invoke SetValue passing it in as a param? Is it possible 

} 

किसी भी संकेत दिए गए?

+0

आप ऐसा क्यों करना चाहते हैं? अगर संपत्ति का निजी सेटटर है, तो यह ऑब्जेक्ट के बाहर से बदलना नहीं है! जो फ़ंक्शन आप प्रस्तावित कर रहे हैं वह आपके प्रोग्राम के अर्थशास्त्र को तोड़ देता है। –

+1

@VladislavZorov मैं ऐसी टिप्पणी देख रहा था और मैं आपका विचार साझा करता हूं। इस उदाहरण में एक तीसरी पार्टी डीटीओ को यूनिट टेस्ट में प्राथमिकता दी जानी चाहिए और ऐसा करने का यह सबसे आसान तरीका होगा। प्रतिबिंब का भी इसका उपयोग होता है। – Anastasiosyal

+0

संभावित डुप्लिकेट [कैसे एक संपत्ति चयनकर्ता अभिव्यक्ति मूल्य सेट करें >] (http://stackoverflow.com/questions/8107134/how-set-value-a-property-selector-expressionfunct-tresult) http: // stackoverflow.com/questions/5075484/property-selector-expressionfunct-how-to-get-set-value-to-selected-property – nawfal

उत्तर

91

आप को धोखा देने और एक विस्तार विधि के साथ जीवन को आसान बना सकता है:

public static class LambdaExtensions 
{ 
    public static void SetPropertyValue<T, TValue>(this T target, Expression<Func<T, TValue>> memberLamda, TValue value) 
    { 
     var memberSelectorExpression = memberLamda.Body as MemberExpression; 
     if (memberSelectorExpression != null) 
     { 
      var property = memberSelectorExpression.Member as PropertyInfo; 
      if (property != null) 
      { 
       property.SetValue(target, value, null); 
      } 
     } 
    } 
} 

और उसके बाद:

var myCustomerInstance = new Customer(); 
myCustomerInstance.SetPropertyValue(c => c.Title, "Mr"); 

कारण है कि इस आसान है क्योंकि आप पहले से लक्ष्य है जो विस्तार पर विधि लागू की जाती है। इसके अलावा लैम्ब्डा अभिव्यक्ति बंद होने के बिना एक साधारण सदस्य अभिव्यक्ति है। आपके मूल उदाहरण में लक्ष्य को बंद करने पर कब्जा कर लिया गया है और अंतर्निहित लक्ष्य और PropertyInfo पर पहुंचना थोड़ा मुश्किल हो सकता है।

+0

+1 बंद होने के बारे में उल्लेख करने के लिए धन्यवाद, यह सोच रहा था कि FieldExpression क्या कर रहा था। इसका मतलब यह होगा कि मूल्य पूरी तरह से सुरुचिपूर्ण नहीं पहुंचा जा सकता है: '(सदस्य चयनकर्ता एक्स्पेरियन.एक्सप्रेसियन सदस्य के रूप में)। कॉन्स्टेंटएक्सप्रेस के रूप में एक्सप्रेशन)। बंद क्षेत्र के मूल्य को प्राप्त करने के लिए वैल्यू'। मुझे एक सामान्य विस्तार विधि जोड़कर आपका दृष्टिकोण पसंद है। – Anastasiosyal

+1

यहां कुछ गलत लगता है। संपत्ति नहीं बदली जाती है, और सीधी कास्ट एक अपवाद फेंकता है: 'सिस्टम का प्रकार ऑब्जेक्ट करने में असमर्थ' System.Linq.Expressions.UnaryExpression 'को' System.Linq.Expressions.MemberExpression 'टाइप करने के लिए। – Stijn

+14

Property.SetValue प्रतिबिंब है । आपको इसका उपयोग नहीं करना चाहिए। 'public static void SetPropertyValue (इस टी लक्ष्य, अभिव्यक्ति <समारोह > memberLamda: – MBoros

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

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