現在、AppDomains を利用するようにプラグイン アーキテクチャを修正しています。私のプラグインと私がオンラインで見つけた多くの例との主な違いは、プラグインが実行されてその結果がメイン アプリケーションに返されるのではなく、私のメイン アプリケーションがプラグインに情報を送信することです。
現状では、ローダーのインスタンスを別の AppDomain に作成します。次に、プラグイン アセンブリの読み込みなど、通常の初期化をすべて行います。この時点で、ローダーのプロキシを使用して、メイン アプリケーションから新しい AppDomain にデータを送信するメソッドを呼び出します。
シリアル化できない引数の型を持ち、MarshalByRefObject から派生していないメソッドを呼び出そうとすると、問題が発生します。
これらのタイプはサードパーティのコードからのものであり、プラグインはそれらを受け取ることを期待しているため、これを行う方法を見つけることができないようです. この質問 ( 「Must be MarshalByRefObject」を C# のような優れた複数継承の切断された言語で解決する方法は? ) を見つけた後、ある種のラッパーを作成することを考えていました。ここでの私の欠点は、サードパーティのコードを変更せずに作成する方法を単純に理解できないことです。
これが私の問題の例です:
// Cant modify this class
class ThirdPartyClass
{
// The properties are also 3rd party and nonserializable. These are accessed by the plugins.
public AnotherClass Property1{ get; set; }
public AnotherClass Property2{ get; set; }
public ThirdPartyClass(){}
}
class Loader : MarshalByRefObject
{
private Plugin plugin;
public Loader()
{
Assembly pluginAssembly = Assembly.LoadFrom("Full/Assembly/Path");
plugin = pluginAssembly.CreateInstance("Full.Plugin.Name") as Plugin;
}
public void DoSomething(ThirdPartyClass o)
{
...
plugin.DoSomethingElse(o);
}
}
class PluginManager
{
void Main(ThirdPartyClass o)
{
AppDomain pluginAppDomain = AppDomain.CreateDomain("Plugin AppDomain");
Loader loader = pluginAppDomain.CreateInstanceFromAndUnwrap("Full/Loader/Path", "Full.Loader.Name") as Loader;
// This is where I would have a problem.
loader.DoSomething(o);
}
}
どんな助けでも大歓迎です。