2010-10-13 20 views
0

J'essaie de créer un archétype de type plug-in pour mon projet. Je voudrais pouvoir charger un assemblage, obtenir un type dérivé d'une classe de base abstraite dans mon projet, l'instancier et charger ce type dérivé dans l'objet de traitement principal.Réflexion - Impossible de créer une nouvelle instance d'objet C#

Mon problème maintenant est que lorsque j'instancie l'objet de l'ensemble reflété, il est toujours nul. Je pense que le problème peut résider dans le fait que l'assembly référencé possède des DLL tierces qu'il utilise. Voici le code: la seule exception qui est touchée est la dernière.

static void Main(string[] args) 
{ 
    string engineFilePath = ConfigurationManager.AppSettings["EngineFilesDirectory"] 
     + "\\" + ConfigurationManager.AppSettings["EngineDllFileName"]; 
    Assembly asm = Assembly.LoadFile(engineFilePath); 

    Type engineType = asm.GetType(ConfigurationManager.AppSettings["EngineType"]); 

    if (!engineType.IsSubclassOf(typeof(EngineConcrete))) 
    { 
     throw new ArgumentException("Engine is not derived from base implimentation."); 
    } 

    object engineInstance = asm.CreateInstance(engineType.Namespace + "." + engineType); 


    if (engineInstance == null) 
    { 
     //always thrown at this point 
     throw new Exception(string.Format("Engine object is null.")); 
    } 

    return; 
} 

Si je change la ligne de instanciation à Activator.CreateInstance(engineType), je reçois une erreur disant que l'un des l'être dll 3ème partie référencée par l'assemblée réfléchie ne peut pas être trouvé, mais ils sont dans le même répertoire que le. dll étant réfléchi.

Il existe également un constructeur public pour le type reflété. Il n'a aucun paramètre et hérite de la classe EngineConcrete.

Répondre

1

Je pense que nul est ce que vous obtenez quand le type ne peut pas être trouvé; le nom de l'espace de nom plus le nom du type peuvent ne pas suffire (problèmes de nommage forts). Que se passe-t-il si vous placez les DLLs tierces dans le répertoire de l'application en cours d'exécution, pas dans le répertoire du plugin?

+0

Résolu la dernière pièce. Je vous remercie –

1

Ceci est le bogue: engineType.Namespace + "." + engineType - cette expression est évaluée en "The.Namespace.The.Namespace.Type" au lieu de "The.Namespace.Type". Utilisez la classe engineType.FullName ou la classe Activator.CreateInstance et utilisez le engineType directement.

Mise à jour: Notez que MSDN indique "... ou null si typeName n'est pas trouvé." À propos de la valeur de retour Assembly.CreateInstance.

+0

Résolu le problème initial. Mais encore reçu "FileNotFoundError" –

+0

Encore une fois, en regardant dans MSDN, 'FileNotFoundExceotion' est levée quand" typeName nécessite un assembly dépendant qui n'a pas pu être trouvé. "Voir http://msdn.microsoft.com/en-us/library/dex1ss7c (v = VS.90) .aspx. –

0

Le problème est que le CLR ne trouve pas les assemblys tiers car ils ne se trouvent pas dans un dossier en cours de vérification.

Vous pouvez ajouter un gestionnaire d'événements pour l'événement AppDomain.CurrentDomain.AssemblyResolve pour gérer ces cas. Ci-dessous un exemple d'implémentation qui a fonctionné pour moi où les assemblys sont chargés dynamiquement à partir d'un dossier "Plugins" contenu dans le dossier bin:

class Program 
{ 
    static string _PluginDirectory; 
    static string PluginDirectory 
    { 
     get 
     { 
      if (_PluginDirectory == null) 
      { 
       _PluginDirectory = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), @"Plugins"); 
      } 
      return _PluginDirectory; 
     } 
    } 

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) 
    { 
     AssemblyName assemblyName = new AssemblyName(args.Name); 
     return Assembly.LoadFile(System.IO.Path.Combine(PluginDirectory, assemblyName.Name + ".dll")); 
    } 

    static void Main(string[] args) 
    { 
     AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 

     var asm = Assembly.LoadFile(System.IO.Path.Combine(PluginDirectory, @"Plugin.dll")); 

     var transmogrifier = asm.CreateInstance("Plugin.ConcreteTransmogrifier") as Common.Transmogrifier; 

     if (transmogrifier != null) 
     { 
      Console.WriteLine(transmogrifier.Transmogrify("Wowzers!")); 
     } 
    } 
} 
Questions connexes