619 votes

L'obtention de tous les types qui implémentent une interface avec C# 3.0

L'aide de 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 en minimisant les itérations?

C'est ce que je veux ré-écrire:

foreach (Type t in this.GetType().Assembly.GetTypes())
    if (t is IMyInterface)
        ; //do stuff

904voto

Darren Kopp Points 27704

La mienne serait ce en c# 3.0 :)

var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
    .SelectMany(s => s.GetTypes())
    .Where(p => type.IsAssignableFrom(p));

En gros, le moins d'itérations sera toujours:

loop assemblies  
 loop types  
  see if implemented.

83voto

Ben Watkins Points 101

Cela a fonctionné pour moi. C'boucles bien que les classes et les vérifications pour voir si elles sont derrived de myInterface

 foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes().Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface))))
 {
    //do stuff
 }

Ben

63voto

Judah Himango Points 27365

Pour trouver tous les types dans une assemblée de mettre en œuvre IFoo interface:

var results = from type in someAssembly.GetTypes()
              where typeof(IFoo).IsAssignableFrom(type)
              select type;

Notez que Ryan Rinaldi suggestion était incorrecte. Il sera de retour 0 types. Vous ne pouvez pas écrire

where type is IFoo

parce que le type est un Système.Type de l'instance, et ne sera jamais de type IFoo. Au lieu de cela, vous vérifiez pour voir si IFoo est assignable à partir de la nature. Qui vous permettra d'obtenir les résultats que vous attendiez.

Aussi, Adam Wright suggestion, qui est actuellement marqué comme réponse, la réponse est incorrecte, et pour la même raison. Au moment de l'exécution, vous verrez 0 types revenir, parce que tout le Système.Type de cas n'étaient pas IFoo des réalisateurs.

22voto

hillstuk Points 151

D'autres réponses ici utiliser IsAssignableFrom. Vous pouvez également utiliser FindInterfaces de la System d'espace de noms, comme décrit ici.

Voici un exemple qui vérifie que toutes les assemblées en cours d'exécution de l'assemblée dossier, à la recherche pour les classes qui implémentent une interface particulière (en évitant de LINQ pour plus de clarté).

    static void Main()
    {
        const string qualifiedInterfaceName = "Interfaces.IMyInterface";
        var interfaceFilter = new TypeFilter(InterfaceFilter);

        var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

        var di = new DirectoryInfo(path);
        foreach (var file in di.GetFiles("*.dll"))
        {
            try
            {
                var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);

                foreach (var type in nextAssembly.GetTypes())
                {
                    var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
                    if (myInterfaces.Length > 0)
                    {
                        // This class implements the interface
                    }
                }
            }
            catch (BadImageFormatException)
            {
                // Not a .net assembly  - ignore
            }                
        }
    }

    public static bool InterfaceFilter(Type typeObj, Object criteriaObj)
    {
        return typeObj.ToString() == criteriaObj.ToString();
    }

Vous pouvez définir une liste d'interfaces si vous voulez correspondre à plus d'un.

En termes de "minimum" de code, ce qui peut être réduit, par exemple par l'utilisation de LINQ dans l' foreach. Gardez à l'esprit que "minimal" ne signifie pas nécessairement efficace, ou facilement de débogage, ou facilement comprise par quelqu'un d'autre...

18voto

Lasse V. Karlsen Points 148037

boucle par tous les assemblys chargés, en boucle par tous leurs types, et de vérifier si elles implémentent l'interface.

quelque chose comme:

Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
{
    foreach (Type t in asm.GetTypes())
    {
        if (ti.IsAssignableFrom(t))
        {
            // here's your type in t
        }
    }
}

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