2011-01-14 21 views
47

Potrzebuję szukać określonych typów we wszystkich złożeniach w witrynie sieci Web lub aplikacji Windows, czy istnieje prosty sposób na zrobienie tego? Podobnie jak w przypadku fabryki kontrolerów ASP.NET MVC wygląda ona na wszystkie zespoły kontrolerów.Znajdź typy we wszystkich złożeniach

Dzięki.

Odpowiedz

79

Istnieją dwa kroki do osiągnięcia tego celu:

  • AppDomain.CurrentDomain.GetAssemblies() zapewnia wszystkie zespoły załadowane w bieżącej domenie aplikacji.
  • Klasa Assembly zapewnia metodę GetTypes() do pobierania wszystkich typów z tego konkretnego zespołu.

Stąd kod może wyglądać następująco:

foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    foreach (Type t in a.GetTypes()) 
    { 
     // ... do something with 't' ... 
    } 
} 

Aby wyszukać określonych typów (np realizacji danego interfejsu, dziedziczy od wspólnego przodka lub cokolwiek) będziesz musiał się z filtrem wyniki. Jeśli potrzebujesz tego w wielu miejscach w swojej aplikacji, dobrym pomysłem jest zbudowanie klasy pomocniczej zapewniającej różne opcje. Na przykład często stosowałem filtry prefiksów przestrzeni nazw, filtry implementacji interfejsów i filtry dziedziczenia.

Aby uzyskać szczegółową dokumentację, zapoznaj się z artykułami MSDN here i here.

+0

Oczywiście, jeśli zamierzałeś zrobić filtrowanie na tych typach i złożeniach, używałbyś LINQ, prawda? ;) –

+6

@Niall Connaughton To kwestia osobistych preferencji. –

+2

Znalazłem sytuacje, gdy robiąc to powoduje wyjątek, okazało się, ponieważ moja aplikacja generuje dynamiczne złożeń, tylko gotcha, aby być świadomym. Możesz zidentyfikować zespoły dynamiczne i pominąć je tak, jak ten http://stackoverflow.com/questions/1423733/how-to-tell-if-a-net-assembly-is-dynamic - jeśli to powoduje problem –

26

Łatwy użyciu LINQ: rozwiązanie

IEnumerable<Type> types = 
      from a in AppDomain.CurrentDomain.GetAssemblies() 
      from t in a.GetTypes() 
      select t; 

foreach(Type t in types) 
{ 
    ... 
} 
19

LINQ z sprawdzić, czy zespół jest dynamiczny:

/// <summary> 
/// Looks in all loaded assemblies for the given type. 
/// </summary> 
/// <param name="fullName"> 
/// The full name of the type. 
/// </param> 
/// <returns> 
/// The <see cref="Type"/> found; null if not found. 
/// </returns> 
private static Type FindType(string fullName) 
{ 
    return 
     AppDomain.CurrentDomain.GetAssemblies() 
      .Where(a => !a.IsDynamic) 
      .SelectMany(a => a.GetTypes()) 
      .FirstOrDefault(t => t.FullName.Equals(fullName)); 
} 
4

Najczęściej jesteś zainteresowany tylko w zespołach, które są widoczne z zewnątrz . Dlatego musisz zadzwonić pod numer GetExportedTypes(). Poza tym można wygenerować ReflectionTypeLoadException. Poniższy kod zajmuje się tymi sytuacjami.

public static IEnumerable<Type> FindTypes(Func<Type, bool> predicate) 
{ 
    if (predicate == null) 
     throw new ArgumentNullException(nameof(predicate)); 

    foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 
    { 
     if (!assembly.IsDynamic) 
     { 
      Type[] exportedTypes = null; 
      try 
      { 
       exportedTypes = assembly.GetExportedTypes(); 
      } 
      catch (ReflectionTypeLoadException e) 
      { 
       exportedTypes = e.Types; 
      } 

      if (exportedTypes != null) 
      { 
       foreach (var type in exportedTypes) 
       { 
        if (predicate(type)) 
         yield return type; 
       } 
      } 
     } 
    } 
} 
Powiązane problemy