2010-04-16 13 views
68

मैं एक सामान्य विधि बनाने की कोशिश कर रहा हूं जो कक्षा पर एक विशेषता को पढ़ेगा और उस मान को रनटाइम पर वापस कर देगा। मैं यह कैसे करूं?मैं रनटाइम पर कक्षा पर एक विशेषता कैसे पढ़ूं?

नोट: डोमेन नाम विशेषता क्लास DomainNameAttribute का है।

[DomainName("MyTable")] 
Public class MyClass : DomainBase 
{} 

क्या मैं उत्पन्न करने के लिए कोशिश कर रहा हूँ:

//This should return "MyTable" 
String DomainNameValue = GetDomainName<MyClass>(); 
+1

आधिकारिक माइक्रोसॉफ्ट लिंक: http://msdn.microsoft.com/en-us/library/71s1zwct.aspx – Mahesh

+2

महत्वपूर्ण परिणाम सवाल यह है कि के साथ विधानसभा में सभी प्रकार प्राप्त करने के लिए कस्टम विशेषता http://stackoverflow.com/questions/2656189/how-do-i-read-an-attribute-on-a-class-at-runtime –

उत्तर

163
public string GetDomainName<T>() 
{ 
    var dnAttribute = typeof(T).GetCustomAttributes(
     typeof(DomainNameAttribute), true 
    ).FirstOrDefault() as DomainNameAttribute; 
    if (dnAttribute != null) 
    { 
     return dnAttribute.Name; 
    } 
    return null; 
} 

अद्यतन:

इस विधि आगे किसी भी विशेषता के साथ काम करने सामान्यीकृत किया जा सकता है:

public static class AttributeExtensions 
{ 
    public static TValue GetAttributeValue<TAttribute, TValue>(
     this Type type, 
     Func<TAttribute, TValue> valueSelector) 
     where TAttribute : Attribute 
    { 
     var att = type.GetCustomAttributes(
      typeof(TAttribute), true 
     ).FirstOrDefault() as TAttribute; 
     if (att != null) 
     { 
      return valueSelector(att); 
     } 
     return default(TValue); 
    } 
} 

और इस तरह का उपयोग करें:

string name = typeof(MyClass) 
    .GetAttributeValue((DomainNameAttribute dna) => dna.Name); 
+5

प्रश्न का उत्तर देने में आपकी परिश्रम के लिए धन्यवाद! – Zaffiro

+1

इस एक्सटेंशन विधि को सदस्यइफ़ो, एक प्रकार का बेस क्लास और सभी प्रकार के कम से कम * अधिकांश * - सदस्यों के विस्तार से आगे बढ़ाया जा सकता है। ऐसा करने से गुण, फ़ील्ड और यहां तक ​​कि ईवेंट से गुणों को पढ़ने की अनुमति देने के लिए इसे खोल दिया जाएगा। –

+2

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

2

यहाँ एक अच्छा ट्यूटोरियल अगर आप इसे http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx

ब्याज की विशेष रूप से करने के लिए आप अनुभाग यहाँ है से पहले नहीं देखा है, विशेषता को एक्सेस करने के लिए कहा जाता है http://msdn.microsoft.com/en-us/library/aa288454(VS.71).aspx#vcwlkattributestutorialanchor3

9
System.Reflection.MemberInfo info = typeof(MyClass); 
object[] attributes = info.GetCustomAttributes(true); 

for (int i = 0; i < attributes.Length; i++) 
{ 
    if (attributes[i] is DomainNameAttribute) 
    { 
     System.Console.WriteLine(((DomainNameAttribute) attributes[i]).Name); 
    } 
} 
+3

@ किसी भी: डारिन का समाधान अधिक सुरुचिपूर्ण है। – Merritt

+0

+1 आपके लिए प्रयास किया गया –

+1

और "var" का उपयोग न करने के लिए +1, इसलिए यह समझना आसान है कि यह कैसे काम करता है। – RenniePet

4

मैं डैरिन दिमित्रोव के जवाब के लिए इस्तेमाल किया कक्षा में किसी भी सदस्य के लिए सदस्य विशेषताओं को प्राप्त करने के लिए एक सामान्य विस्तार बनाने के लिए (विशेषता के बजाए एक वर्ग के लिए es)। मैं इसे यहाँ पोस्ट कर रहा हूँ क्योंकि दूसरों इसे उपयोगी पाते हो सकता है:

public static class AttributeExtensions 
{ 
    /// <summary> 
    /// Returns the value of a member attribute for any member in a class. 
    ///  (a member is a Field, Property, Method, etc...)  
    /// <remarks> 
    /// If there is more than one member of the same name in the class, it will return the first one (this applies to overloaded methods) 
    /// </remarks> 
    /// <example> 
    /// Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass': 
    ///  var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description); 
    /// </example> 
    /// <param name="type">The class that contains the member as a type</param> 
    /// <param name="MemberName">Name of the member in the class</param> 
    /// <param name="valueSelector">Attribute type and property to get (will return first instance if there are multiple attributes of the same type)</param> 
    /// <param name="inherit">true to search this member's inheritance chain to find the attributes; otherwise, false. This parameter is ignored for properties and events</param> 
    /// </summary>  
    public static TValue GetAttribute<TAttribute, TValue>(this Type type, string MemberName, Func<TAttribute, TValue> valueSelector, bool inherit = false) where TAttribute : Attribute 
    { 
     var att = type.GetMember(MemberName).FirstOrDefault().GetCustomAttributes(typeof(TAttribute), inherit).FirstOrDefault() as TAttribute; 
     if (att != null) 
     { 
      return valueSelector(att); 
     } 
     return default(TValue); 
    } 
} 

प्रयोग उदाहरण:

//Read System.ComponentModel Description Attribute from method 'MyMethodName' in class 'MyClass' 
var Attribute = typeof(MyClass).GetAttribute("MyMethodName", (DescriptionAttribute d) => d.Description); 
+0

विरासत व्युत्पन्न गुणों पर काम नहीं करती है - इसके लिए, आपको एक अलग स्थैतिक विधि (System.Attribute.GetCustomAttributes) को कॉल करने की आवश्यकता होगी http://stackoverflow.com/a/7175762/184910 – murraybiscuit

2

डैरिन दिमित्रोव का पहला समाधान का एक सरलीकृत संस्करण:

public string GetDomainName<T>() 
{ 
    var dnAttribute = typeof(T).GetCustomAttribute<DomainNameAttribute>(true); 
    if (dnAttribute != null) 
    { 
     return dnAttribute.Name; 
    } 
    return null; 
} 
0
' Simplified Generic version. 
Shared Function GetAttribute(Of TAttribute)(info As MemberInfo) As TAttribute 
    Return info.GetCustomAttributes(GetType(TAttribute), _ 
            False).FirstOrDefault() 
End Function 

' Example usage over PropertyInfo 
Dim fieldAttr = GetAttribute(Of DataObjectFieldAttribute)(pInfo) 
If fieldAttr IsNot Nothing AndAlso fieldAttr.PrimaryKey Then 
    keys.Add(pInfo.Name) 
End If 

शायद जेनेरिक फ़ंक्शन इनलाइन के शरीर का उपयोग करना उतना ही आसान है। यह MyClass प्रकार के प्रकार को सामान्य बनाने के लिए मुझे कोई समझ नहीं आता है।

string DomainName = GetAttribute<DomainNameAttribute>(typeof(MyClass)).Name 
// null reference exception if MyClass doesn't have the attribute. 
18

ऐसा करने के लिए पहले से ही एक विस्तार है।

namespace System.Reflection 
{ 
    // Summary: 
    //  Contains static methods for retrieving custom attributes. 
    public static class CustomAttributeExtensions 
    { 
     public static T GetCustomAttribute<T>(this MemberInfo element, bool inherit) where T : Attribute; 
    } 
} 

तो:

var attr = typeof(MyClass).GetCustomAttribute<DomainNameAttribute>(false); 
return attr != null ? attr.DomainName : ""; 
संबंधित मुद्दे