2016-07-21 6 views
1

私は、ユーザーがDLLを動的にロードおよびアンロードできるホットスワップ可能なプラグインシステムを構築しようとしています。できるだけコアアプリケーションを再起動する必要はありません。そのため、私は多くの機能を外部ライブラリに移行しています。私が調べた研究から、2番目の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

編集ありがとう!しかし、ローダーはメインプログラムにあります。 DLLからロードしようとするとCreateInstanceが失敗しませんか? – Bioniclegenius

+0

しかし、Loaderをロードしようとしないときは、PluginManagerをロードしようとします。それが問題です。これがAppDomain.CreateInstanceに渡しています。 –

関連する問題