2009-03-10 11 views
8

मैं एक कस्टम विशेषता का उपयोग कर रहा हूं यह निर्धारित करने के लिए कि कैसे एक वर्ग के सदस्यों को फॉर्म पोस्ट (भुगतान गेटवे) के रूप में पोस्ट करने के लिए गुणों के लिए मैप किया जाता है। मेरे पास कस्टम विशेषता केवल ठीक काम कर रही है, और मैं "नाम" द्वारा विशेषता प्राप्त करने में सक्षम हूं, लेकिन सदस्य द्वारा विशेषता प्राप्त करना चाहूंगा।कक्षा सदस्यों पर कस्टम विशेषताएं

उदाहरण के लिए:

getFieldName("name"); 

बनाम

getFieldName(obj.Name); 

योजना एक postable स्ट्रिंग में सदस्यों के साथ वर्ग क्रमानुसार करने के लिए एक विधि लिखने के लिए है।

foreach (MemberInfo i in (typeof(CustomClass)).GetMember("Name")) 
{ 
    foreach (object at in i.GetCustomAttributes(true)) 
    { 
     PropertyMapping map = at as PropertyMapping; 
     if (map != null) 
     { 
      ret += map.FieldName; 
     } 
    } 
} 

अग्रिम धन्यवाद:

यहाँ परीक्षण कोड इस बिंदु है, जहां सेवानिवृत्त एक स्ट्रिंग है और PropertyMapping कस्टम विशेषता है पर मेरे पास है!

+0

इसके अलावा, यदि कोई बेहतर दृष्टिकोण है तो मैं सभी कान हूं :) – ccook

उत्तर

9

आप वास्तव में नहीं कर सकते ऐसा करें, जब तक कि आप सी # 3.0 का उपयोग नहीं कर रहे हैं, इस मामले में आपको LINQ (ehm, अभिव्यक्ति पेड़) पर भरोसा करना होगा।

आप क्या करते हैं कि आप लैम्ब्डा अभिव्यक्ति के लिए एक डमी विधि बनाते हैं जो संकलक अभिव्यक्ति वृक्ष उत्पन्न करता है (कंपाइलर प्रकार की जांच करता है)। फिर आप सदस्य पाने के लिए उस पेड़ में खुदाई करते हैं। इसलिए जैसा:

static FieldInfo GetField<TType, TMemberType>(
    Expression<Func<TType, TMemberType>> accessor) 
{ 
    var member = accessor.Body as MemberExpression; 
    if (member != null) 
    { 
     return member.Member as FieldInfo; 
    } 
    return null; // or throw exception... 
} 

निम्नलिखित वर्ग को देखते हुए:

class MyClass 
{ 
    public int a; 
} 

आप इस तरह मेटा डेटा प्राप्त कर सकते हैं: उस क्षेत्र आप तो किसी भी की खुदाई कर सकते हैं के लिए एक संदर्भ के साथ

// get FieldInfo of member 'a' in class 'MyClass' 
var f = GetField((MyClass c) => c.a); 

सामान्य तरीके से विशेषता है। यानी प्रतिबिंब।

static TAttribute GetAttribute<TAttribute>( 
    this MemberInfo member) where TAttribute: Attribute 
{ 
    return member.GetCustomAttributes(typeof(TAttribute), false) 
     .Cast<TAttribute>().FirstOrDefault<TAttribute>(); 
} 

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

var attr = GetField((MyClass c) => c.a).GetAttribute<DisplayNameAttribute>(); 
Console.WriteLine(attr.DisplayName); 

वहां उस कोड में एक भी शाब्दिक स्ट्रिंग नहीं है।

+0

वाह, धन्यवाद! यह निश्चित रूप से काम करता है, मैंने अभी इसका परीक्षण किया है। बहुत अच्छा :) – ccook

+0

उत्तर के रूप में चिह्नित करने के लिए मत भूलना;) –

+0

मुझे लगता है कि वापसी सदस्य। फील्डइन्फो के रूप में याद रखें; सदस्यइन्फो का रिटर्न प्रकार होना चाहिए। अन्यथा कास्टिंग हमेशा शून्य लौटता है। – Jeff

4

आप थोड़ा और बस इसे का आधा कर सकते हैं:

foreach (PropertyMapping attrib in 
     Attribute.GetCustomAttributes(i, typeof(PropertyMapping))) 
    { 
     ret += map.FieldName; // whatever you want this to do... 
    } 

btw; आपको Attribute शब्द के साथ विशेषताओं को समाप्त करने की आदत बनाना चाहिए। भले ही यह डुप्लिकेशन का कारण बनता है (देखें [XmlAttributeAttribute])।

हालांकि - पुनः क्रमिकरण; यह हमेशा तुच्छ नहीं है। कोड का एक भ्रामक राशि Json.NET आदि जैसे क्रमबद्धता चौखटे में चला जाता है सामान्य दृष्टिकोण एक प्रकार कनवर्टर पाने के लिए हो सकता है, लेकिन कई मायनों में यह एक PropertyDescriptor साथ आसान है:

foreach (PropertyDescriptor prop in TypeDescriptor.GetProperties(obj)) 
    { 
     Console.WriteLine("{0}={1}", 
      prop.Name, prop.Converter.ConvertToInvariantString(
       prop.GetValue(obj))); 
    } 
+0

धन्यवाद मार्क, मैंने आपके दो बदलावों को सुझाव दिया है :) – ccook

+0

क्या यह संपत्ति डिस्क्रिप्टर का उपयोग करना बेहतर होगा? – ccook

+0

यह इस बात पर निर्भर करता है कि आप क्या कर रहे हैं ;-P PropertyDescriptor * सही * कनवर्टर आदि प्राप्त करने में थोड़ा आसान बनाता है - लेकिन ज्यादातर मामलों में वे समान हैं। कुछ चीजें हैं जो आप एक * xor * दूसरे के साथ कर सकते हैं, लेकिन अधिकांश चीजें या तो में की जा सकती हैं। –

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