2015-11-07 2 views
0

J'avais installé un petit système de plugin basé sur l'utilisation d'interfaces. Mais j'ai découvert que les interfaces ne pouvaient pas être sérialisées et tout mon système de sauvegarde dépend des fichiers de sérialisation, qui contiendront ces plugins. J'ai donc décidé d'échanger l'interface pour une classe abstraite. Ce qui a bien fonctionné. Mais il semble que ma solution actuelle nécessite une interface.Les assemblages peuvent-ils être chargés sans utiliser d'interfaces?

Les types pour l'assembly affichent uniquement null et Resources. Donc je devine juste que charger des assemblages de cette manière ne peut pas être fait avec des classes abstraites? Y a-t-il un moyen de le faire sans utiliser d'interfaces?

public List<EnginePluginBase> GetEnginePlugins(string directory) 
{ 
    if (string.IsNullOrEmpty(directory)) 
     return null; 

    List<EnginePluginBase> plugins = new List<EnginePluginBase>(); 
    foreach (FileInfo file in new DirectoryInfo(directory).GetFiles("*.dll")) 
    { 
     Assembly currentAssembly = Assembly.LoadFile(file.FullName); 

     foreach (Type type in GetTypesLoaded(currentAssembly)) 
     { 
      if (type != typeof(EnginePluginBase)) 
       continue; 

      EnginePluginBase plugin = (EnginePluginBase)Activator.CreateInstance(type); 
      plugins.Add(plugin); 
     } 
    } 

    return plugins; 
} 

private Type[] GetTypesLoaded(Assembly assembly) 
{ 
    Type[] types; 
    try 
    { 
     types = assembly.GetTypes(); 
    } 
    catch (ReflectionTypeLoadException e) 
    { 
     types = e.Types.Where(t => t != null).ToArray(); 
    } 

    return types; 
} 
+0

vous pouvez le faire avec classe abstraite –

+0

Il nous manque le code de GetTypesLoaded. Quoi qu'il en soit, ce 'si (type! = Typeof (EnginePluginBase))' semble incorrect: vous devriez trouver (je suppose) des types qui héritent de EnginePluginBase. Essayez d'utiliser 'IsAssignableFrom':' if (! Typeof (EnginePluginBase) .IsAssignableFrom (type)) ' –

+0

@GianPaolo GetTypesLoaded est juste assembly.GetTypes() avec une vérification nulle. Je vais essayer votre suggestion. – ernest

Répondre

1

Votre GetTypesLoaded semble trop indulgent avec des exceptions: S'il y a exception dans les types de chargement, vous devez comprendre la raison. Essayez d'examiner l'exception que vous obtenez (e.LoaderExceptions est un bon candidat)

Comme je l'ai dit dans le commentaire, modifier le chèque pour le type que vous recherchez: changement

if (type != typeof(EnginePluginBase)) 
    continue; 

à

if (! typeof(EnginePluginBase).IsAssignableFrom(type)) 
    continue; 

Cela devrait fonctionner à la fois avec la classe de base abstraite (EnginePluginBase) ou l'interface (telle IEnginePlugin)

En outre, il fonctionne avec des types hérités ne sont pas directement de EnginePluginBase - à savoir une classe qui hérite d'une autre classe qui hérite de EnginePluginBase (ou instruments IEnginePlugin)

+0

Il s'avère que j'utilisais une bibliothèque qui n'avait pas été mise à jour pour la classe abstraite. Donc, il essayait toujours d'utiliser l'interface. Voilà pourquoi ça ne fonctionnait pas. Mais peu importe, mon contrôle de type original n'aurait pas fonctionné. J'ai donc accepté votre réponse. – ernest

1

changement type !=typeof(EnginePluginBase)-type.BaseType !=typeof(EnginePluginBase) comme une classe de base aussi Je ne sais pas quelle est cette méthode GetTypesLoaded. voici le code que j'utilise et travaille pour moi je pense que cela devrait marcher pour vous.

Assembly asm = null; 
asm = Assembly.LoadFrom(strProtocolDll); 
Type[] assemblyTypes = asm.GetTypes(); 
    foreach (Type module in assemblyTypes) 
    { 
    if (typeof(ProtocolBase) == module.BaseType) 
     { 
      return (ProtocolBase)Activator.CreateInstance(module); 
     } 
    }