जाँच करें कि क्या संपत्ति में विशेषता है


158

एक वर्ग में एक संपत्ति को देखते हुए, विशेषताओं के साथ - यह निर्धारित करने का सबसे तेज़ तरीका क्या है यदि इसमें एक विशेषता दी गई है? उदाहरण के लिए:

    [IsNotNullable]
    [IsPK]
    [IsIdentity]
    [SequenceNameAttribute("Id")]
    public Int32 Id
    {
        get
        {
            return _Id;
        }
        set
        {
            _Id = value;
        }
    }

यह निर्धारित करने के लिए सबसे तेज़ तरीका क्या है कि उदाहरण के लिए इसमें "IsIdentity" विशेषता है?

जवाबों:


279

विशेषताओं को पुनः प्राप्त करने का कोई तेज़ तरीका नहीं है। लेकिन कोड इस तरह दिखना चाहिए ( हारून के लिए क्रेडिट ):

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var hasIsIdentity = Attribute.IsDefined(pi, typeof(IsIdentity));

यदि आपको विशेषता गुण पुनः प्राप्त करने की आवश्यकता है

var t = typeof(YourClass);
var pi = t.GetProperty("Id");
var attr = (IsIdentity[])pi.GetCustomAttributes(typeof(IsIdentity), false);
if (attr.Length > 0) {
    // Use attr[0], you'll need foreach on attr if MultiUse is true
}

63
यदि आपको केवल विशेषता के अस्तित्व की जांच करनी है, और इसमें से किसी भी जानकारी को प्राप्त नहीं करना है, तो Attribute.IsDefinedकोड की एक पंक्ति और बदसूरत सरणियों / कास्टिंग को समाप्त कर देगा।
Aaronaught

4
कुछ मैं सिर्फ इस के साथ भाग गया है कुछ विशेषताएँ उनके विशेषता नाम के लिए एक अलग प्रकार है। उदाहरण के लिए System.ComponentModel.DataAnnotations.Schema में "NotMapped" का उपयोग [NotMapped]कक्षा के रूप में किया जाता है, लेकिन इसका उपयोग करने के लिए आपको पता लगाना होगाAttribute.IsDefined(pi, typeof(NotMappedAttribute))
Qjimbo

2
सामान्य अधिभार का उपयोग करना आसान हो सकता है:IsIdentity[] attr = pi.GetCustomAttributes<IsIdentity>(false);
Mojtaba

@ क्यूजिमो (या शायद कोई और पढ़ रहा है) विशेषताएँ आमतौर पर उनके नाम के "गुण" भाग के बिना उपयोग की जाती हैं, लेकिन हो सकती हैं। एक सम्मेलन आपको इसे बाहर करने की अनुमति देता है, इसलिए आमतौर पर वास्तविक प्रकार में इसके नाम के अंत में विशेषता होती है, लेकिन इसका उपयोग नहीं किया जाता है।
जिम वोल्फ

44

यदि आप .NET 3.5 का उपयोग कर रहे हैं, तो आप अभिव्यक्ति पेड़ों के साथ कोशिश कर सकते हैं। यह प्रतिबिंब से अधिक सुरक्षित है:

class CustomAttribute : Attribute { }

class Program
{
    [Custom]
    public int Id { get; set; }

    static void Main()
    {
        Expression<Func<Program, int>> expression = p => p.Id;
        var memberExpression = (MemberExpression)expression.Body;
        bool hasCustomAttribute = memberExpression
            .Member
            .GetCustomAttributes(typeof(CustomAttribute), false).Length > 0;
    }
}

7
FYI करें एक प्रश्न आपके उत्तर के बारे में पूछा गया है। stackoverflow.com/questions/4158996/…
ग्रेग

12

आप किसी दिए गए MemberInfo पर विशेषता को पढ़ने के लिए एक सामान्य (सामान्य) विधि का उपयोग कर सकते हैं

public static bool TryGetAttribute<T>(MemberInfo memberInfo, out T customAttribute) where T: Attribute {
                var attributes = memberInfo.GetCustomAttributes(typeof(T), false).FirstOrDefault();
                if (attributes == null) {
                    customAttribute = null;
                    return false;
                }
                customAttribute = (T)attributes;
                return true;
            }

7

@Hans Passant द्वारा उत्तर को अपडेट और / या बढ़ाने के लिए मैं संपत्ति की पुनर्प्राप्ति को विस्तार विधि में अलग कर दूंगा। यह GetProperty () विधि में गंदा जादू स्ट्रिंग को हटाने का अतिरिक्त लाभ है

public static class PropertyHelper<T>
{
    public static PropertyInfo GetProperty<TValue>(
        Expression<Func<T, TValue>> selector)
    {
        Expression body = selector;
        if (body is LambdaExpression)
        {
            body = ((LambdaExpression)body).Body;
        }
        switch (body.NodeType)
        {
            case ExpressionType.MemberAccess:
                return (PropertyInfo)((MemberExpression)body).Member;
            default:
                throw new InvalidOperationException();
        }
    }
}

आपका परीक्षण फिर दो लाइनों में सिमट जाता है

var property = PropertyHelper<MyClass>.GetProperty(x => x.MyProperty);
Attribute.IsDefined(property, typeof(MyPropertyAttribute));

7

यदि आप एक पोर्टेबल क्लास लाइब्रेरी पीसीएल (मेरी तरह) में ऐसा करने की कोशिश कर रहे हैं, तो यहां बताया गया है कि आप इसे कैसे कर सकते हैं :)

public class Foo
{
   public string A {get;set;}

   [Special]
   public string B {get;set;}   
}

var type = typeof(Foo);

var specialProperties = type.GetRuntimeProperties()
     .Where(pi => pi.PropertyType == typeof (string) 
      && pi.GetCustomAttributes<Special>(true).Any());

फिर आप उन संपत्तियों की संख्या की जांच कर सकते हैं जिनके पास यह विशेष संपत्ति है यदि आपको आवश्यकता है।


7

यह अब अभिव्यक्ति पेड़ों और विस्तार विधियों के बिना नए C # सुविधा के साथ एक सुरक्षित तरीके से किया जा सकता है nameof():

Attribute.IsDefined(typeof(YourClass).GetProperty(nameof(YourClass.Id)), typeof(IsIdentity));

nameof () C # 6 में पेश किया गया था


6

आप Attribute.IsDefined पद्धति का उपयोग कर सकते हैं

https://msdn.microsoft.com/en-us/library/system.attribute.isdefined(v=vs.110).aspx

if(Attribute.IsDefined(YourProperty,typeof(YourAttribute)))
{
    //Conditional execution...
}

आप ऐसी संपत्ति प्रदान कर सकते हैं जिसे आप विशेष रूप से देख रहे हैं या आप प्रतिबिंब, कुछ का उपयोग करके उन सभी के माध्यम से पुनरावृति कर सकते हैं:

PropertyInfo[] props = typeof(YourClass).GetProperties();

यह संकलन नहीं है। आप YourProperty या YourAttribute के चारों ओर [] का उपयोग नहीं कर सकते हैं
रोल करता है

हर पिछले उत्तर ने वर्ग, संपत्ति और विशेषता नामों पर मान्यताओं का उपयोग किया है जो मैंने पीछा किया था।
फ्रांसिस मसिग्नैक

अब प्रकट होता है।
रोल

2

यह एक बहुत पुराना सवाल है, लेकिन मैंने इस्तेमाल किया है

मेरी विधि में यह पैरामीटर है लेकिन इसे बनाया जा सकता है:

Expression<Func<TModel, TValue>> expression

फिर इस विधि में:

System.Linq.Expressions.MemberExpression memberExpression 
       = expression.Body as System.Linq.Expressions.MemberExpression;
Boolean hasIdentityAttr = System.Attribute
       .IsDefined(memberExpression.Member, typeof(IsIdentity));
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.