2011-03-10 16 views
5

İlk defa, kendimi manuel olarak derleme taraması yapmak zorundaydım. BenÖzel nitelikler için tüm sınıfları ve yöntemleri taramak için en iyi yöntemler

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(); 

Tek bir taramada Bunu yapmak için şu 2 birleştirmeyi deneyin veya Should yöntem seviyesine dışarı genişletmek için yeterince basitti

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(); 

Bana ayarlamak hangi C# - how enumerate all classes with custom class attribute? geldi sadece erken optimizasyona mı düşüyor? (tarama sadece uygulama başlangıcında yürütülür)

Metotlarda türden çok daha fazla yöntem bulunduğundan, yöntemlerin taranması için daha uygun olan farklı bir şey var mı?

+0

Ben meclisleri ve türlerini numaralandıran meclisleri ve türleri önbelleğe olacak şekilde, bulma ve özelliklerini başlatmasını çok daha hızlı olacak bahse gidiyorum anlamsız olacak. – Gabe

cevap

3

Yansıma çok yavaş

Oraya temelleri gitmek düşünüyorum ...: gibi

Yani sonuç tarama yöntemi görünebilir. Ek tam taramanın gerçekleşmesini önlemek için kodunuzu biraz değiştirmenizi tavsiye ederim.

Bunu birden çok kez yapmanız gerekiyorsa, sonuçları ne zamana uygun olursa olsun önbelleğe almayı da öneririm. Bu sözde kodu gibi

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

Bunu en iyi duruma getirebileceğinizi düşünüyorum, ancak özelliklerin yöntemlere ve türlere nasıl yerleştirileceğine bağlı olarak değişir. Özel nitelikli tüm türlerinizin ve/veya özel özniteliklerinizin belirli derlemelerde tanımlandığını biliyorsanız, yalnızca bu derlemeleri tarayabilirsiniz.

Ayrıca gibi bazı yöntemler tanımlayabiliriz:

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

ve ana tarama yönteminde bu yöntemleri kullanın.

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>(); 
} 
İlgili konular