163 votes

Comment énumérer toutes les classes avec un attribut de classe personnalisé ?

Question basée sur Exemple MSDN .

Disons que nous avons quelques classes C# avec HelpAttribute dans une application de bureau autonome. Est-il possible d'énumérer toutes les classes avec cet attribut ? Est-il judicieux de reconnaître les classes de cette manière ? L'attribut personnalisé serait utilisé pour lister les options de menu possibles, la sélection d'un élément fera apparaître à l'écran l'instance de cette classe. Le nombre de classes/articles augmentera lentement, mais de cette façon nous pouvons éviter de les énumérer tous ailleurs, je pense.

4voto

Lo Sauer Points 5469

En cas de Limites du portable .NET le code suivant devrait fonctionner :

    public static IEnumerable<TypeInfo> GetAtributedTypes( Assembly[] assemblies, 
                                                           Type attributeType )
    {
        var typesAttributed =
            from assembly in assemblies
            from type in assembly.DefinedTypes
            where type.IsDefined(attributeType, false)
            select type;
        return typesAttributed;
    }

ou pour un grand nombre d'assemblages en utilisant la méthode de l'état de boucle. yield return :

    public static IEnumerable<TypeInfo> GetAtributedTypes( Assembly[] assemblies, 
                                                           Type attributeType )
    {
        foreach (var assembly in assemblies)
        {
            foreach (var typeInfo in assembly.DefinedTypes)
            {
                if (typeInfo.IsDefined(attributeType, false))
                {
                    yield return typeInfo;
                }
            }
        }
    }

1voto

sommmen Points 22

Ceci est une autre version du code fourni par Philip Trade-Ideas, J'ai condensé le code en linq, et l'ai inséré dans une belle fonction statique que vous pouvez simplement déposer dans le projet.

Original : https://stackoverflow.com/a/41411243/4122889

J'ai également ajouté AsParallel() - sur ma machine avec suffisamment de cœurs, etc., et avec un projet de taille "normale" (ce qui est totalement subjectif), c'était le plus rapide et le plus efficace.

Sans AsParallel() cela a pris 1,5 secondes pour environ 200 résultats, et avec cela, cela a pris environ quelques millisecondes - donc cela me semble le plus rapide.

Notez que cela ignore les assemblages dans le GAC.

private static IEnumerable<IEnumerable<T>> GetAllAttributesInAppDomain<T>()
{
    var definedIn = typeof(T).Assembly.GetName().Name;
    var assemblies = AppDomain.CurrentDomain.GetAssemblies();

   var res = assemblies.AsParallel()
        .Where(assembly => (!assembly.GlobalAssemblyCache) && ((assembly.GetName().Name == definedIn) ||
                                                               assembly.GetReferencedAssemblies()
                                                                   .Any(a => a.Name == definedIn))
            )
        .SelectMany(c => c.GetTypes())
        .Select(type => type.GetCustomAttributes(typeof(T), true)
            .Cast<T>()
            )
        .Where(c => c.Any());

    return res;
}

Utilisation :

var allAttributesInAppDomain = GetAllAttributesInAppDomain<ExportViewAttribute>();

Notez que si vous n'avez qu'un seul attribut par classe, et non plusieurs, il est plus facile d'aplatir le résultat à partir de IEnumerable<IEnumerable<T>> a IEnumerable<T> comme ça :

var allAttributesInAppDomainFlattened = allAttributesInAppDomain.SelectMany(c => c);

Rappelez-vous, cela utilise IEnumerable alors appelez ToList() pour exécuter réellement la fonction.

0voto

Tachyon Points 1130

Nous pouvons améliorer la réponse d'Andrew et convertir le tout en une seule requête LINQ.

    public static IEnumerable<Type> GetTypesWithHelpAttribute(Assembly assembly)
    {
        return assembly.GetTypes().Where(type => type.GetCustomAttributes(typeof(HelpAttribute), true).Length > 0);
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X