En utilisant la réflexion, comment puis-je obtenir tous les types qui implémentent une interface avec C # 3.0 / .NET 3.5 avec le moins de code et minimiser les itérations?
Voici ce que je veux réécrire:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
Réponses:
Le mien serait ceci en c # 3.0 :)
Fondamentalement, le moins d'itérations sera toujours:
la source
.Where(p => type.IsAssignableFrom(p) && !p.IsInterface);
pour la filtrer (oup.IsClass
).List<string>
ne met pas en œuvre,IEnumerable<object>
mais cette méthode retournera vrai dans .Net 4.0 en raison de la covariance qui est en effet incorrecte. La bonne réponse est ici.Where(p => type.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract
Cela a fonctionné pour moi. Il parcourt les classes et vérifie si elles sont dérivées de myInterface
la source
Pour rechercher tous les types dans un assembly qui implémentent l'interface IFoo:
Notez que la suggestion de Ryan Rinaldi était incorrecte. Il renverra 0 types. Tu ne peux pas écrire
car type est une instance System.Type et ne sera jamais de type IFoo. Au lieu de cela, vous vérifiez si IFoo est attribuable à partir du type. Cela obtiendra les résultats attendus.
De plus, la suggestion d'Adam Wright, qui est actuellement marquée comme réponse, est également incorrecte, et pour la même raison. Au moment de l'exécution, vous verrez 0 types revenir, car toutes les instances System.Type n'étaient pas des implémenteurs IFoo.
la source
J'apprécie que c'est une très vieille question, mais j'ai pensé ajouter une autre réponse aux futurs utilisateurs car toutes les réponses à ce jour utilisent une forme de
Assembly.GetTypes
.Bien que GetTypes () renvoie en effet tous les types, cela ne signifie pas nécessairement que vous pouvez les activer et donc potentiellement lancer un
ReflectionTypeLoadException
.Un exemple classique pour ne pas pouvoir activer un type serait lorsque le type retourné est
derived
debase
maisbase
est défini dans un assembly différent de celui dederived
, un assembly que l'assembly appelant ne référence pas.Alors disons que nous avons:
Si dans
ClassC
lequel se trouveAssemblyC
nous faisons alors quelque chose selon la réponse acceptée:Ensuite, il lancera un
ReflectionTypeLoadException
.En effet , sans référence à
AssemblyA
enAssemblyC
vous ne seriez pas en mesure de:En d'autres termes
ClassB
n'est pas chargeable ce qui est quelque chose que l'appel à GetTypes vérifie et lance.Donc, pour qualifier en toute sécurité l'ensemble de résultats pour les types chargeables, conformément à cet article de Phil Haacked Obtenir tous les types dans un code Assembly et Jon Skeet, vous devriez plutôt faire quelque chose comme:
Et alors:
la source
CreateInstance
pour chacun d'entre eux, et une exception a été levée quand il essayait de créer l'interface réelle (ce qui m'a confus pendant un certain temps quand je pensais que l'interface réelle était hors de propos dans cette solution). J'ai donc changé le code enGetLoadableTypes(assembly).Where(interfaceType.IsAssignableFrom).Where(t => !(t.Equals(interfaceType))).ToList();
.D'autres réponses ici utilisent
IsAssignableFrom
. Vous pouvez également utiliser àFindInterfaces
partir de l'System
espace de noms, comme décrit ici .Voici un exemple qui vérifie tous les assemblys dans le dossier de l'assembly en cours d'exécution, à la recherche de classes qui implémentent une certaine interface (en évitant LINQ pour plus de clarté).
Vous pouvez configurer une liste d'interfaces si vous souhaitez en faire correspondre plusieurs.
la source
parcourir tous les assemblys chargés, parcourir tous leurs types et vérifier s'ils implémentent l'interface.
quelque chose comme:
la source
Cela a fonctionné pour moi (si vous le souhaitez, vous pouvez exclure les types de système dans la recherche):
la source
Edit: je viens de voir l'édition pour clarifier que la question d'origine était pour la réduction des itérations / du code et c'est bien beau comme exercice, mais dans des situations du monde réel, vous voudrez la mise en œuvre la plus rapide, indépendamment de la fraîcheur du LINQ sous-jacent.
Voici ma méthode Utils pour parcourir les types chargés. Il gère les classes régulières ainsi que les interfaces, et l'option excludeSystemTypes accélère énormément les choses si vous recherchez des implémentations dans votre propre base de code / tierce.
Ce n'est pas joli, j'avoue.
la source
excludeSystemTypes
deux fois en unif
?L'autre réponse ne fonctionnait pas avec une interface générique .
Celui-ci le fait, il suffit de remplacer typeof (ISomeInterface) par typeof (T).
Donc avec
nous obtenons tous les assemblages
est utilisé pour exclure l'interface et les abstraites et
pour les avoir dans une liste.
la source
Il n'y a pas de moyen facile (en termes de performances) de faire ce que vous voulez faire.
La réflexion fonctionne principalement avec les assemblys et les types, vous devrez donc obtenir tous les types d'assembly et les interroger pour obtenir la bonne interface. Voici un exemple:
Cela vous donnera tous les types qui implémentent IMyInterface dans l'assembly MyAssembly
la source
Encore mieux lors du choix du lieu de montage. Filtrez la plupart des assemblys si vous savez que toutes vos interfaces implémentées sont dans les mêmes Assembly.DefinedTypes.
Par Can Bilgin
la source
La méthode OfType Linq peut être utilisée exactement pour ce type de scénarios:
https://docs.microsoft.com/fr-fr/dotnet/api/system.linq.enumerable.oftype?view=netframework-4.8
la source
Il existe déjà de nombreuses réponses valides, mais j'aimerais ajouter une implémentation d'anthère en tant qu'extension de type et une liste de tests unitaires pour illustrer différents scénarios:
Cet algorithme prend en charge les scénarios suivants:
la source
la source
J'ai des exceptions dans le code linq donc je le fais de cette façon (sans extension compliquée):
la source
Vous pouvez utiliser du LINQ pour obtenir la liste:
Mais est-ce vraiment plus lisible?
la source