2016-07-21 197 views
1

我正在嘗試構建一個可熱插拔的插件系統,用戶可以在其中動態加載和卸載dll。核心應用程序儘可能少地重新啓動是非常必要的,所以我將相當多的功能轉移到外部庫。從我已經發現的研究中,我需要創建第二個AppDomain並將該DLL加載到該中,然後傳遞參數等來運行它。目前,我相信我的大部分程序都能正常工作,但是在從CreateInstance對象上調用AppDomain.Unwrap()函數時遇到錯誤。錯誤如下:C#AppDomain無法加載DLL

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

下面是加載代碼:

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"); 
    } 

此行是其中拋出的錯誤:

loader = (Loader)obj.Unwrap(); 

外部DLL在幾乎沒有任何代碼它,因爲這是一個概念證明。它如下:

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); 
    } 
    } 
} 

編輯:這是加載器類的代碼。

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); 
    } 
    } 

回答

0

它看起來像你想在AppDomain創建類型PluginManager的對象,然後投其代理的類型Loader(這是從您的代碼示例丟失)。

的問題是在這些線路:

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

如果您既可以創建的Loader而不是PluginManager實例它的工作 - 或 - 轉換成PluginManager,而不是Loader。我的猜測是前者:

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

(更換LoaderNamespace以實物。)

+0

我已經更新了代碼,包括裝載機演員。你能用一些代碼解釋你的答案嗎?我不確定你想要我做什麼。 – Bioniclegenius

+0

感謝您的編輯!但Loader在主程序中。當它嘗試從dll加載它時,CreateInstance不會失敗嗎? – Bioniclegenius

+0

但是你不會嘗試加載Loader,你嘗試加載PluginManager。那就是問題所在。這就是你傳遞給AppDomain.CreateInstance的內容。 –