2015-02-17 2 views
6

मैं एक वर्ग जो INotifyPropertyChanged इस तरह लागू करता है पर:स्विच-प्रकरण Class.PropertyName (नहीं मान)

public class Person : INotifyPropertyChanged { 

    public event PropertyChangedEventHandler PropertyChanged; 

    string _color; 
    public string Color 
    { 
     get{ return _color; } 
     set 
     { 
      _color = value; 
      RaisePropertyChanged(); 
     } 
    } 

    ...   

    private void RaisePropertyChanged([CallerMemberName]string prop = "") 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(prop)); 
    } 
} 

जब Color संपत्ति सेटर कहा जाता है, यह RaisePropertyChanged() जो स्वत: "Color" यानी संपत्ति नाम हो जाता है कॉल और PropertyChangedEventArgs को पॉप्युलेट करने के लिए इसका उपयोग करता है। संपत्ति नाम में मैन्युअल रूप से टाइप करने के बजाय।

यह अच्छा है क्योंकि यह आपके कोड में संभावित बग को रोकता है क्योंकि आपको मैन्युअल रूप से संपत्ति का नाम टाइप नहीं करना पड़ता है। आपके कोड को रीफैक्टर करते समय भी मदद करता है क्योंकि आप किसी स्ट्रिंग को हार्ड-कोडिंग नहीं कर रहे हैं।

मेरे प्रश्न
मैं PropertyChanged के लिए एक ईवेंट हैंडलर की है। संपत्ति नामों को स्ट्रिंग के रूप में हार्ड कोडिंग किए बिना मैं स्विच-केस निर्माण का उपयोग कैसे कर सकता हूं। तो इस तरह कुछ:

void Person_PropertyChanged(object sender, PropertyChangedEventArgs e){ 
    switch (e.PropertyName) 
    { 
     case PropertyNameOf(Person.Color); 
      //some stuff 
      break; 
     default: 
      break; 
    } 
} 

क्या यह संभव है? मैं ऐसा करना चाहता हूं इसलिए मैं ऊपर बताए गए लाभों को रख सकता हूं।

+0

आपको 'केस' के अंदर क्या करने की आवश्यकता है? –

+0

@NateBarbettini कुछ सामान। मैंने इसे छोड़ दिया क्योंकि मुझे नहीं लगता कि यह – Krimson

+3

प्रश्न के लिए प्रासंगिक था आप सी # 6 के 'nameof' ऑपरेटर की तलाश में हैं। – SLaks

उत्तर

7

आप जो चाहते हैं उसे करने के लिए आप Expression<Func<T>> का उपयोग कर सकते हैं।

इस विधि को परिभाषित करें:

private string ToPropertyName<T>(Expression<Func<T>> @this) 
{ 
    var @return = string.Empty; 
    if (@this != null) 
    { 
     var memberExpression = @this.Body as MemberExpression; 
     if (memberExpression != null) 
     { 
      @return = memberExpression.Member.Name; 
     } 
    } 
    return @return; 
} 

तो फिर तुम यह लिख सकते हैं:

void Person_PropertyChanged(object sender, PropertyChangedEventArgs e){ 
    switch (e.PropertyName) 
    { 
     case ToPropertyName(() => Person.Color); 
      //some stuff 
      break; 
     default: 
      break; 
    } 
} 

अब आप कुछ दृढ़ता से टाइप खुशी है। :-)


switch और गंदा if/then/else आप ऐसा कर सकते हैं बिना स्विच की तरह कार्यक्षमता प्राप्त करने के लिए:

void Person_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    var @switch = new Dictionary<string, Action>() 
    { 
     { ToPropertyName(() => Person.Color),() => { /* some stuff */ } }, 
     { ToPropertyName(() => Person.Size),() => { /* some other stuff */ } }, 
     { ToPropertyName(() => Person.Shape),() => { /* some more stuff */ } }, 
    }; 

    if (@switch.ContainsKey(e.PropertyName)) 
    { 
     @switch[e.PropertyName](); 
    } 
    else 
    { 
     /* default stuff */ 
    } 
} 
+0

यह शानदार है। –

+0

बहुत बढ़िया! आपका बहुत बहुत धन्यवाद! – Krimson

+0

एक प्रश्न।'रंग' के बाद से आप 'व्यक्ति' रंग कैसे कर सकते हैं एक गैर स्थैतिक क्षेत्र है? – Krimson

5

में सी # 6.0, आप nameof() कीवर्ड का उपयोग कर सकते हैं।

कीवर्ड को संकलन समय पर स्ट्रिंग अक्षर द्वारा प्रतिस्थापित किया गया है। तो यह कोड है कि देखने के एक प्रदर्शन बिंदु पर रनटाइम पर अपने प्रतीक के नाम खोदता साथ लैम्ब्डा अभिव्यक्ति का उपयोग कर की तुलना में बेहतर है, और यह भी switch() बयान के साथ काम करता है:

switch(e.PropertyName) 
{ 
    case nameof(Foo.Bar): 
     break; 
} 

तुम भी एक संकलन समय त्रुटि है, तो मिल जाएगा आप कक्षा में संपत्ति का नाम बदलते हैं, लेकिन इसे अपने स्विच स्टेटमेंट में बदलना भूल जाते हैं। तो यह दृष्टिकोण बहुत कम बगप्रोन है।

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