2016-07-21 3 views
1

Je tente de créer un système de plug-in remplaçable à chaud dans lequel l'utilisateur peut charger et décharger dynamiquement des DLL. Il est nécessaire que l'application de base redémarre le moins possible, donc je déplace à la place la plupart des fonctionnalités vers des bibliothèques externes. À partir de ce que j'ai découvert, j'ai besoin de créer un second AppDomain et de charger la DLL dans celui-ci, puis de simplement transmettre les paramètres et autres pour l'exécuter. Actuellement, je crois que la majeure partie du programme fonctionne, mais je rencontre une erreur lors de l'appel de la fonction AppDomain.Unwrap() sur l'objet à partir de CreateInstance. L'erreur est la suivante:C# AppDomain ne peut pas charger la DLL

System.InvalidCastException: Unable to cast transparent proxy to type 'Program1.Loader'. 

Voici le code de chargement:

try { 
    unload(dom,out loader,true); 
    dom=null; 
    AppDomainSetup dms = new AppDomainSetup(); 
    dms.ConfigurationFile=Environment.CurrentDirectory+Path.DirectorySeparatorChar+"Program1.exe.config"; 
    dms.ApplicationBase=Environment.CurrentDirectory+Path.DirectorySeparatorChar+"Plugins"; 
    Evidence ev = AppDomain.CurrentDomain.Evidence; 
    dom=AppDomain.CreateDomain("PluginManager",ev,dms); 
    AssemblyName an = AssemblyName.GetAssemblyName(Environment.CurrentDirectory+"\\Plugins\\PluginManager.dll"); 

    ObjectHandle obj = dom.CreateInstance(an.FullName,"PluginManager.PluginManager"); 
    loader = (Loader)obj.Unwrap(); 
    loader.LoadAssembly(@"PluginManager.dll"); 

    if(!suppressOutput) 
     Console.WriteLine("Reload successful."); 
    } 
    catch(Exception e) { 
    unload(dom,out loader,true); 
    loader=null; 
    Console.WriteLine("PluginManager failed loading. Enter \"reload\" to try again.\n"); 
    Console.Write(e+"\n\n"); 
    } 

Cette ligne est l'endroit où l'erreur est renvoyée:

loader = (Loader)obj.Unwrap(); 

La DLL externe n'a presque aucun code il, puisque c'est une preuve de concept. Il est comme suit:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace PluginManager { 
    public class PluginManager:MarshalByRefObject { 
    public void run(string comm) { 
     Console.WriteLine(comm); 
    } 
    } 
} 

Modifier: Voici le code pour la classe loader.

class Loader:MarshalByRefObject { 
    private Assembly _assembly; 

    public override object InitializeLifetimeService() { 
     return null; 
    } 

    public void LoadAssembly(string path) { 
     _assembly=Assembly.Load(AssemblyName.GetAssemblyName(path)); 
    } 

    public object ExecuteStaticMethod(string typeName,string methodName,params object[] parameters) { 
     Type type = _assembly.GetType(typeName); 
     MethodInfo method = type.GetMethod(methodName,BindingFlags.Static|BindingFlags.Public); 
     return method.Invoke(null,parameters); 
    } 
    } 

Répondre

0

On dirait que vous essayez de créer un objet du type PluginManager dans le AppDomain puis jeté son proxy du type Loader (qui est absent de votre exemple de code).

Le problème est dans ces lignes:

ObjectHandle obj = dom.CreateInstance(an.FullName,"PluginManager.PluginManager"); 
loader = (Loader)obj.Unwrap(); 

Il travaillerait si vous soit créer une instance de Loader au lieu de PluginManager - ou - CAST pour PluginManager au lieu de Loader. Je suppose l'ancien:

ObjectHandle obj = dom.CreateInstance(an.FullName,"LoaderNamespace.Loader"); 

(Remplacer LoaderNamespace avec le vrai.)

+0

J'ai mis à jour le code pour inclure la distribution du chargeur. Pourriez-vous expliquer votre réponse avec un peu de code, s'il vous plaît? Je ne suis pas sûr de ce que tu veux que je fasse. – Bioniclegenius

+0

Merci pour le montage! Mais Loader est dans le programme principal. Le CreateInstance échouerait-il quand il essaye de le charger de la DLL? – Bioniclegenius

+0

Mais vous n'essayez pas de charger Loader, vous essayez de charger PluginManager. C'est le problème. C'est ce que vous passez à AppDomain.CreateInstance. –