2011-03-10 12 views
5

के लिए सभी वर्गों और विधियों को स्कैन करने के लिए सर्वोत्तम प्रथाएं पहली बार मुझे वास्तव में मैन्युअल रूप से स्कैनिंग करने की आवश्यकता होती है। मैं जो मुझेकस्टम विशेषता

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

कौन सा काफी सरल विधि के स्तर के लिए बाहर का विस्तार करने के लिए था के साथ सेट अप

var methodsWithAttributes = 
    (from assembly in AppDomain.CurrentDomain.GetAssemblies() 
    from type in assembly.GetTypes() 
    from method in type.GetMethods() 
    let attributes = method.GetCustomAttributes(typeof(SomeAttribute), true) 
    where attributes != null && attributes.Length > 0 
    select new { Type = type, Method = method, 
      Attributes = attributes.Cast<SomeAttribute>() }) 
    .ToList(); 

मैं एक ही स्कैन में इन 2 गठबंधन करने के लिए यह करने के लिए कोशिश करना चाहिए, या C# - how enumerate all classes with custom class attribute? में आए क्या यह सिर्फ शुरुआती अनुकूलन में पड़ रहा है? (स्कैनिंग केवल ऐप स्टार्ट पर निष्पादित होगी)

क्या कुछ अलग है जो तरीकों की स्कैनिंग के लिए अधिक अनुकूल होगा क्योंकि असेंबली में प्रकारों की तुलना में कहीं अधिक तरीके हैं?

+0

मैं शर्त लगा सकता है कि विधानसभाओं और प्रकार की गणना खोजने और अपनी विशेषताओं instantiating, ऐसी है कि है विधानसभाओं और प्रकार कैशिंग की तुलना में बहुत तेजी से होने जा रहा है जा रहा हूँ व्यर्थ होने जा रहा है। – Gabe

उत्तर

3

प्रतिबिंब बहुत धीमी है ...

मैं आपको लगता है गया है मूल बातें वहाँ जाना। मैं आपको अतिरिक्त पूर्ण स्कैन होने वाली जगह से बचने के लिए थोड़ा सा कोड बदलने की सलाह दूंगा।

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

Sorta इस छद्म कोड की तरह:

... (optional caches) ... 
IDictionary<Type, IEnumerable<Attributes>> typeAttributeCache = new ... 
IDictionary<MethodInfo, IEnumerable<Attributes>> methodAttributeCache = new ... 

... (in another method or class) ... 
foreach assembly in GetAssemblies() 
    foreach type in assembly.GetTypes()   
    typeAttributes = typeAttributeCache.TryGet(...) // you know the correct syntax, trying to be brief 

    if (typeAttributes is null) 
     typeAttributes = type.GetCustomAttributes().OfType<TypeImLookingFor>(); 
     typeAttributeCache[type] = typeAttributes; 

    foreach methodInfo in type.GetMethods()   
     methodAttributes = methodAttributeCache.TryGet(...) // same as above 

     if (methodAttributes is null) 
     methodAttributes = methodInfo.GetCustomAttributes().OfType<TypeImLookingFor>(); 
     methodAttributeCache[type] = methodAttributes; 

    // do what you need to do 
2

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

इसके अलावा, आप की तरह, कुछ तरीकों को परिभाषित कर सकते हैं:

- IEnumerable<Type> GetAllTypesFromAssemblyByAttribute<TAttribute>(Assembly assembly) where TAttribute : Attribute 
- IEnumerable<MethodInfo> GetAllMethodsFromTypeByAttribute<TAttribute>(Type type) where TAttribute : Attribute 

और अपने मुख्य स्कैनिंग विधि में इन विधियों का उपयोग करें।

तो अपने परिणाम विधि स्कैन दिखाई दे सकता है जैसे:

private void ScanAndDoSmth<TAttribute>(IEnumerable<Assembly> assemblies) 
where TAttribute : Attribute 
{ 
    var result = 
     from assembly in assemblies 
     from type in GetAllTypesFromAssemblyByAttribute<TAttribute>(assembly) 
     let attributes = type.GetCustomAttributes(typeof(TAttribute), true) 
     where attributes != null && attributes.Length > 0 
     select new { Type = type, Attributes = attributes.Cast<TAttribute>(); 
} 
संबंधित मुद्दे