2013-01-21 15 views
6

Eventuali duplicati:
Finding all classes with a particular attributeTrova tutte le classi con una specifica attribut

In un'assemblea vorrei ottenere tutte le istanze di un particolare attributo di classe. In altre parole mi piacerebbe avere l'elenco delle classi che hanno un attributo specifico.

Normalmente si dispone di una classe per cui è possibile recuperare l'attributo utilizzando il metodo GetCustomAttributes.

È possibile avere un elenco di chi ha un attributo particolare?

+0

Si intende un elenco di classi con attributi specifici in un assieme? In quale ambito hai il tuo elenco di classi? – LukeHennerley

+1

A tutti, chi ha downvoted il post! Per favore, lasciate commenti per i vostri downvotes. –

risposta

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

Oppure:

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 mio metodo di riferimento (100000 iterazioni):

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 

Codice di riferimento:

[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

L'uso di LINQ potrebbe velocizzare le cose qui invece di eseguire il ciclo sulle classi, ma ottiene comunque gli stessi risultati :) – LukeHennerley

+0

Proviamo un benchmark quindi! –

+1

Ragazzi Non sono interessato alla velocità qui. La chiarezza è il mio concernno. Lo eseguirò solo una volta l'intera applicazione. Comunque grazie appico il tuo sforzo. – mathk

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

È possibile farlo utilizzando reflection. Questo ti darà un List<Type> di tutti i tipi all'interno dell'assieme corrente che hanno 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

Sì ok, questo è quello che volevo evitare. Il dover eseguire il ciclo su tutta la classe di un assembly paticolare non è molto bello. Ma se questa è l'unica soluzione. – mathk

+0

@mathk Sfortunatamente lo è; Tuttavia, non dovrebbe essere così lento eseguire il controllo per tipo. Se hai intenzione di riutilizzare questo controllo in più posizioni, puoi sempre memorizzare nella cache i risultati. –

+0

Lo userei solo una volta all'inizio dell'applicazione. Non sono preoccupato dalla velocità. Ma chiedere al runtime di creare tutto fa la reificazione è qualcosa di cui non sono affatto fan. Qualche metodo statico sulla classe Attribute come: 'GetAllType', o' GetAllProperties', ... sarebbe stato più carino. – mathk

0

Senza esempi di codice, uno presuppone una List<Type> o un Assembly.

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