2010-03-07 15 views
6

मैंने हाल ही में पोस्टशर्प के साथ प्रयोग करना शुरू कर दिया है और मुझे INotifyPropertyChanged के कार्यान्वयन को स्वचालित करने के लिए एक विशेष रूप से सहायक पहलू मिला है। आप उदाहरण here देख सकते हैं। मूल कार्यक्षमता उत्कृष्ट है (सभी गुणों को अधिसूचित किया जाएगा), लेकिन ऐसे मामले हैं जहां मैं अधिसूचना को दबा सकता हूं।विशेषता के साथ पोस्टशर्प मल्टीकास्ट को दबाकर

उदाहरण के लिए, मुझे पता चलेगा कि एक विशेष संपत्ति कन्स्ट्रक्टर में एक बार सेट की जाती है और फिर कभी नहीं बदलेगी। इस प्रकार, NotifyPropertyChanged के लिए कोड को उत्सर्जित करने की कोई आवश्यकता नहीं है। ओवरहेड न्यूनतम होता है जब कक्षाओं को अक्सर तत्काल नहीं किया जाता है और मैं स्वचालित रूप से जेनरेट की गई संपत्ति से क्षेत्र-समर्थित संपत्ति में स्विच करके और क्षेत्र में लिखकर समस्या को रोक सकता हूं। हालांकि, जैसा कि मैं इस नए उपकरण को सीख रहा हूं, यह जानना उपयोगी होगा कि कोड पीढ़ी को दबाने के लिए किसी विशेषता के साथ संपत्ति को टैग करने का कोई तरीका है या नहीं। मैं इस तरह कुछ करने के लिए सक्षम होने के लिए करना चाहते हैं:

[NotifyPropertyChanged] 
public class MyClass 
{ 
    public double SomeValue { get; set; } 

    public double ModifiedValue { get; private set; } 

    [SuppressNotify] 
    public double OnlySetOnce { get; private set; } 

    public MyClass() 
    { 
     OnlySetOnce = 1.0; 
    } 
} 

उत्तर

5

आप एक MethodPointcut बजाय एक MulticastPointcut की है, यानी उपयोग कर सकते हैं का उपयोग Linq-ओवर-परावर्तन और PropertyInfo.IsDefined के खिलाफ फिल्टर (आपकी विशेषता)।

private IEnumerable<PropertyInfo> SelectProperties(Type type) 
    { 
     const BindingFlags bindingFlags = BindingFlags.Instance | 
      BindingFlags.DeclaredOnly 
              | BindingFlags.Public; 

     return from property 
        in type.GetProperties(bindingFlags) 
       where property.CanWrite && 
        !property.IsDefined(typeof(SuppressNotify)) 
       select property; 
    } 

    [OnLocationSetValueAdvice, MethodPointcut("SelectProperties")] 
    public void OnSetValue(LocationInterceptionArgs args) 
    { 
     if (args.Value != args.GetCurrentValue()) 
     { 
      args.ProceedSetValue(); 

      this.OnPropertyChangedMethod.Invoke(null); 
     } 
    } 
+0

उत्कृष्ट, धन्यवाद। यह एक बहुत ही शक्तिशाली उपकरण है और मेरी परियोजना सभी थकाऊ INotifyPropertyChanged नलसाजी के बिना काफी साफ महसूस करता है। –

0

FYI करें, मैं Sharpcrafters वेबसाइट पर उदाहरण के साथ कुछ समस्या थी और निम्न परिवर्तन करने के लिए किया था:

/// <summary> 
    /// Field bound at runtime to a delegate of the method <c>OnPropertyChanged</c>. 
    /// </summary> 
    [ImportMember("OnPropertyChanged", IsRequired = true, Order = ImportMemberOrder.AfterIntroductions)] 
    public Action<string> OnPropertyChangedMethod; 

मुझे लगता है कि यह OnPropertyChanged सदस्य परिचय दे रहा था, लेकिन आयात करने से पहले यह एक था बनने का मौका इससे OnPropertySet विफल हो जाएगा क्योंकि यह .OnPropertyChangedMethod शून्य था।

3

एक और आसान तरीका, का उपयोग करें:

[NotifyPropertyChanged(AttributeExclude=true)] 

... एक विशेष विधि के लिए विशेषताओं को दबाने के लिए। यह तब भी काम करता है जब कक्षा से जुड़ी एक वैश्विक विशेषता है (ऊपर दिए गए उदाहरण में)।

यहाँ पूर्ण उदाहरण कोड है:

[NotifyPropertyChanged] 
public class MyClass 
{ 
    public double SomeValue { get; set; } 

    public double ModifiedValue { get; private set; } 

    [NotifyPropertyChanged(AttributeExclude=True)] 
    public double OnlySetOnce { get; private set; } 

    public MyClass() 
    { 
     OnlySetOnce = 1.0; 
    } 
} 

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

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