2010-05-23 12 views
2

J'écris une interface qui sera implémentée par beaucoup de classes, et j'écris une classe qui contiendra une collection d'instances de ces implémentations. Chaque classe aura un constructeur par défaut.Accès dynamique des classes d'un espace de noms donné

Donc, existe-t-il un moyen simple (par exemple d'utiliser une sorte de réflexion) pour mettre une instance de chacune de ces classes d'implémentation à la collection? En plus de le faire manuellement, ce qui est simple, oui, mais beaucoup de travail et d'erreurs sujettes (que se passe-t-il si j'ignore une implémentation lors de l'écriture de la méthode? Donc, ce que je voudrais, c'est pouvoir parcourir toutes les classes d'un espace de noms donné ou peut-être à travers la liste de toutes les classes disponibles. Ma méthode vérifie ensuite, par réflexion, si la classe donnée implémente l'interface donnée, et si c'est le cas, la met dans la collection.

Merci.

+1

Quelle est la motivation pour ce faire? Un peu de contexte aiderait, car il existe peut-être une solution alternative. –

+0

Ce que j'écris est un cadre de persistance pour un usage personnel. Il effectuera des opérations de sauvegarde/chargement dynamique sur les objets, tout comme la sérialisation, mais je ne peux pas utiliser la sérialisation à des fins diverses. Mon interface a des méthodes comme Save, Load, et les classes d'implémentation contiennent du code pour le mécanisme load/save de différentes classes. – dzs

Répondre

2

Vous devez appeler Assembly.GetTypes() pour obtenir chaque classe dans un assembly, appelez typeof(IMyInterface).IsAssignableFrom pour vérifier les classes qui implémentent l'interface, puis appelez Activator.CreateInstanse pour instancier la classe.

LINQ:

typeof(IMyInterface).Assembly.GetTypes() 
          .Where<Type, bool>(typeof(IMyInterface).IsAssignableFrom) 
          .Select(t => Activator.CreateInstance(typeof(T))) 
          .ToArray() 
+0

Super, merci, cela fonctionne! – dzs

2

Ici, il est sans LinQ, répartis ainsi vous pouvez voir ce qui se passe. Mais sinon, c'est exactement la même chose que ce que SLaks a écrit.

Il obtient toutes les classes implémentant l'interface IFoo.

List<IFoo> items = new List<IFoo>(); 

//Iterate through all types 
foreach (Type type in Assembly.GetExecutingAssembly.GetTypes) { 

    //Check the type is public and not abstract 
    if (!type.IsPublic | type.IsAbstract) 
     continue; 

    //Check if it implements the interface IFoo 
    if (typeof(IFoo).IsAssignableFrom(type)) { 

     //Create an instance of the class 
     //If the constructor has arguments put them after "type" like so: 
     //Activator.CreateInstance(type, arg1, arg2, arg3, etc...) 
     IFoo foo = (IFoo)Activator.CreateInstance(type); 

     //Add the instance to your collection 
     items.Add(foo); 

    } 
} 
+0

Merci pour le code plus explicatif. Et, d'ailleurs, ça semble être une bonne idée de vérifier si la classe n'est pas abstraite. – dzs