2013-01-21 22 views
6

Powiel możliwe:
Finding all classes with a particular attributeZnajdź wszystkie klasy z określonym Attribut

W zespole chciałbym uzyskać wszystkie wystąpienia określonego atrybutu klasy. Innymi słowy chciałbym mieć listę klas, które mają określony atrybut.

Zwykle masz klasę, dla której możesz pobrać atrybut przy użyciu metody GetCustomAttributes.

Czy możliwe jest posiadanie listy osób, które mają określony atrybut?

+0

Masz na myśli listę klas o określonych atrybutach w zespole? W jakim zakresie otrzymujesz listę klas? – LukeHennerley

+1

Do wszystkich, którzy zarzucili post! Proszę zostawić komentarz dla swoich notowań. –

Odpowiedz

3
public static IEnumerable<Type> GetTypesWithMyAttribute(Assembly assembly) 
{ 
    foreach(Type type in assembly.GetTypes()) 
    { 
     if (Attribute.IsDefined(type, typeof(MyAttribute))) 
      yield return type; 
    } 
} 

Lub:

public static List<Type> GetTypesWithMyAttribute(Assembly assembly) 
{ 
    List<Type> types = new List<Type>(); 

    foreach(Type type in assembly.GetTypes()) 
    { 
     if (type.GetCustomAttributes(typeof(MyAttribute), true).Length > 0) 
      types.Add(type); 
    } 

    return types; 
} 

Linq VS moja metoda odniesienia (100000 iteracji):

Round 1 
My Approach:  2088ms 
Linq Approach 1: 7469ms 
Linq Approach 2: 2514ms 

Round 2 
My Approach:  2055ms 
Linq Approach 1: 7082ms 
Linq Approach 2: 2149ms 

Round 3 
My Approach:  2058ms 
Linq Approach 1: 7001ms 
Linq Approach 2: 2249ms 

Kod Benchmark:

[STAThread] 
public static void Main() 
{ 
    List<Type> list; 

    Stopwatch watch = Stopwatch.StartNew(); 

    for (Int32 i = 0; i < 100000; ++i) 
     list = GetTypesWithMyAttribute(Assembly.GetExecutingAssembly()); 

    watch.Stop(); 

    Console.WriteLine("ForEach: " + watch.ElapsedMilliseconds); 

    watch.Restart(); 

    for (Int32 i = 0; i < 100000; ++i) 
     list = GetTypesWithMyAttributeLinq1(Assembly.GetExecutingAssembly()); 

    Console.WriteLine("Linq 1: " + watch.ElapsedMilliseconds); 

    watch.Restart(); 

    for (Int32 i = 0; i < 100000; ++i) 
     list = GetTypesWithMyAttributeLinq2(Assembly.GetExecutingAssembly()); 

    Console.WriteLine("Linq 2: " + watch.ElapsedMilliseconds); 

    Console.Read(); 
} 

public static List<Type> GetTypesWithMyAttribute(Assembly assembly) 
{ 
    List<Type> types = new List<Type>(); 

    foreach (Type type in assembly.GetTypes()) 
    { 
     if (Attribute.IsDefined(type, typeof(MyAttribute))) 
      types.Add(type); 
    } 

    return types; 
} 

public static List<Type> GetTypesWithMyAttributeLinq1(Assembly assembly) 
{ 
    return assembly.GetTypes() 
       .Where(t => t.GetCustomAttributes().Any(a => a is MyAttribute)) 
       .ToList(); 
} 

public static List<Type> GetTypesWithMyAttributeLinq2(Assembly assembly) 
{ 
    return assembly.GetTypes() 
       .Where(t => Attribute.IsDefined(t, typeof(MyAttribute))) 
       .ToList(); 
} 
+0

Używanie LINQ potencjalnie przyspieszałoby tutaj, zamiast zapętlać klasy, ale osiąga takie same wyniki: :) – LukeHennerley

+0

Spróbujmy testu porównawczego! –

+1

Faceci Nie jestem tutaj zainteresowany. Klarowność jest moją konkrecją. Wykonam to tylko raz całą aplikację. W każdym razie dziękuję za wycenę twojego wysiłku. – mathk

1
var list = asm.GetTypes() 
      .Where(t => t.GetCustomAttributes().Any(a => a is YourAttribute)) 
      .ToList(); 
2

Możesz to zrobić, używając reflection. To dostarczy Ci List<Type> wszystkich typów w bieżącym zestawie, które mają MyAttribute.

using System.Linq; 
using System.Reflection; 

// ... 

var asmbly = Assembly.GetExecutingAssembly(); 
var typeList = asmbly.GetTypes().Where(
     t => t.GetCustomAttributes(typeof (MyAttribute), true).Length > 0 
).ToList(); 
+0

Tak, dobrze, właśnie tego chciałem uniknąć. Konieczność zapętlenia się nad całą Klasą zespołu łaty nie jest całkiem przyjemna. Ale jeśli to jedyne rozwiązanie. – mathk

+0

@mathk Niestety tak; Jednak nie powinno być tak powolne, aby wykonać kontrolę każdego typu. Jeśli zamierzasz ponownie użyć tego sprawdzenia w wielu miejscach, zawsze możesz buforować wyniki. –

+0

Używałbym tego tylko raz na początku aplikacji. Nie zależy mi na prędkości. Ale proszenie środowiska wykonawczego, aby wszystko stworzyło, jest czymś, czego nie jestem do końca fanem. Niektóre statyczne metody w klasie Attribute, takie jak: 'GetAllType' lub' GetAllProperties', ... byłyby ładniejsze. – mathk

0

Bez przykładów kodu, jeden zakłada masz List<Type> lub Assembly.

public List<Type> TypesWithAttributeDefined(Type attribute) 
{ 
    List<Type> types = assembly.GetTypes(); 
    return types.Where(t => Attribute.IsDefined(t, attribute)).ToList(); 
} 
Powiązane problemy