web-dev-qa-db-fra.com

Rechercher des types dans tous les assemblages

J'ai besoin de rechercher des types spécifiques dans tous les assemblages d'un site Web ou d'une application Windows, existe-t-il un moyen simple de le faire? Comme à quoi ressemble la fabrique de contrôleurs pour ASP.NET MVC dans tous les assemblys de contrôleurs.

Merci.

56
Brian Mains

Il y a deux étapes pour y parvenir:

  • La AppDomain.CurrentDomain.GetAssemblies() vous donne tous les assemblys chargés dans le domaine d'application actuel.
  • La classe Assembly fournit une méthode GetTypes() pour récupérer tous les types dans cet assembly particulier.

Par conséquent, votre code pourrait ressembler à ceci:

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

Pour rechercher des types spécifiques (par exemple, implémenter une interface donnée, hériter d'un ancêtre commun ou autre), vous devrez filtrer les résultats. Dans le cas où vous devez le faire à plusieurs endroits de votre application, c'est une bonne idée de créer une classe d'assistance offrant différentes options. Par exemple, j'ai couramment appliqué des filtres de préfixe d'espace de noms, des filtres d'implémentation d'interface et des filtres d'héritage.

Pour une documentation détaillée, consultez MSDN ici et ici .

96
Ondrej Tucny

Utilisation simple de Linq:

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

foreach(Type t in types)
{
    ...
}
29
Thomas Levesque

Solution LINQ avec vérification pour voir si l'assemblage est dynamique:

/// <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));
}
27
mheyman

Le plus souvent, vous n'êtes intéressé que par les assemblages visibles de l'extérieur. Pour cela, vous devez appeler GetExportedTypes () Mais en plus de cela, une ReflectionTypeLoadException peut être levée. Le code suivant prend en charge ces situations.

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;
                }
            }
        }
    }
}
5
alex.pino