[C#] कस्टम क्लास विशेषता वाले सभी वर्गों को कैसे समझाते हैं?


Answers

खैर, आपको वर्तमान एप डोमेन में लोड की गई सभी असेंबली में सभी कक्षाओं के माध्यम से गणना करना होगा। ऐसा करने के लिए, आप वर्तमान ऐप डोमेन के लिए AppDomain इंस्टेंस पर GetAssemblies विधि को कॉल करेंगे।

वहां से, आप Assembly में मौजूद प्रकारों को प्राप्त करने के लिए GetExportedTypes (यदि आप केवल सार्वजनिक प्रकार चाहते हैं) या प्रत्येक Assembly पर GetTypes को GetTypes करेंगे।

फिर, आप उस विशेषता के प्रकार को पार करते हुए, प्रत्येक Type उदाहरण पर GetCustomAttributes विधि को कॉल करेंगे जिसे आप GetCustomAttributes चाहते हैं।

आप LINQ का उपयोग अपने लिए इसे सरल बनाने के लिए कर सकते हैं:

var typesWithMyAttribute =
    from a in AppDomain.CurrentDomain.GetAssemblies()
    from t in a.GetTypes()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };

उपर्युक्त क्वेरी आपको प्रत्येक विशेषता को आपके द्वारा लागू विशेषता के साथ, उस पर लागू विशेषता के साथ मिल जाएगी।

ध्यान दें कि यदि आपके आवेदन डोमेन में बड़ी संख्या में असेंबली लोड की गई हैं, तो वह ऑपरेशन महंगा हो सकता है। ऑपरेशन के समय को कम करने के लिए आप समांतर LINQ का उपयोग कर सकते हैं, जैसे:

var typesWithMyAttribute =
    // Note the AsParallel here, this will parallelize everything after.
    from a in AppDomain.CurrentDomain.GetAssemblies().AsParallel()
    from t in a.GetTypes()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };

इसे एक विशिष्ट Assembly पर फ़िल्टर करना सरल है:

Assembly assembly = ...;

var typesWithMyAttribute =
    from t in assembly.GetTypes()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };

और यदि असेंबली में बड़ी संख्या में प्रकार हैं, तो आप समानांतर LINQ का फिर से उपयोग कर सकते हैं:

Assembly assembly = ...;

var typesWithMyAttribute =
    // Partition on the type list initially.
    from t in assembly.GetTypes().AsParallel()
    let attributes = t.GetCustomAttributes(typeof(HelpAttribute), true)
    where attributes != null && attributes.Length > 0
    select new { Type = t, Attributes = attributes.Cast<HelpAttribute>() };
Question

एमएसडीएन उदाहरण के आधार पर प्रश्न।

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




जैसा कि पहले से ही कहा गया है, प्रतिबिंब जाने का रास्ता है। यदि आप इसे अक्सर कॉल करने जा रहे हैं, तो मैं अत्यधिक परिणामों का कैशिंग करने का सुझाव देता हूं, प्रतिबिंब के रूप में, विशेष रूप से प्रत्येक वर्ग के माध्यम से गणना करना, काफी धीमा हो सकता है।

यह मेरे कोड का एक स्निपेट है जो सभी भारित असेंबली में सभी प्रकार के माध्यम से चलता है:

// this is making the assumption that all assemblies we need are already loaded.
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 
{
    foreach (Type type in assembly.GetTypes())
    {
        var attribs = type.GetCustomAttributes(typeof(MyCustomAttribute), false);
        if (attribs != null && attribs.Length > 0)
        {
            // add to a cache.
        }
    }
}



पोर्टेबल .NET सीमाओं के मामले में, निम्न कोड काम करना चाहिए:

    public static IEnumerable<TypeInfo> GetAtributedTypes( Assembly[] assemblies, 
                                                           Type attributeType )
    {
        var typesAttributed =
            from assembly in assemblies
            from type in assembly.DefinedTypes
            where type.IsDefined(attributeType, false)
            select type;
        return typesAttributed;
    }

या लूप-स्टेट आधारित yield return का उपयोग करके बड़ी संख्या में असेंबली के लिए:

    public static IEnumerable<TypeInfo> GetAtributedTypes( Assembly[] assemblies, 
                                                           Type attributeType )
    {
        foreach (var assembly in assemblies)
        {
            foreach (var typeInfo in assembly.DefinedTypes)
            {
                if (typeInfo.IsDefined(attributeType, false))
                {
                    yield return typeInfo;
                }
            }
        }
    }