プラグインフレームワークのコントラクトとして抽象クラスを使用する
-
22-09-2019 - |
質問
抽象クラスを「ホスト」と「プラグイン」の間のコントラクト オブジェクトとして使用できますか?その考え方は、プラグインがコントラクトを継承するということです (これをアダプターと呼びます)。また、フレームワークのすべての参加者が継承する必要があることも理解しています。 MarshalByRefObject
(MBRO)。それで、これが私たちが考えていたことです -
ホスト:
class Host : MarshalByRefObject
{
}
契約:
public abstract class PluginAdapter : MarshalByRefObject
{
}
プラグイン:
class myPlugin : PluginAdapter
{
}
3 つすべてが別々の asm に存在します。ホストはプラグインごとに新しい AppDomain を作成し、PluginAdapter は次のように作成されます。
{
ObjectHandle instHandle = Activator.CreateInstance(
newDomain, data.Assembly.FullName, data.EntryPoint.FullName);
PluginAdapter adapter = (PluginAdapter)instHandle.Unwrap();
}
編集:どこ data
の具体的なタイプです myPlugin
.
私たちは、このフレームワークの実装が機能するかどうか疑問に思っていました。プラグインの派生にインターフェイス (IPlugin) を使用し、コントラクトとして具象クラスを使用する記事を見てきました。これらの記事では、抽象クラスを使用できるとも述べていますが、その実装例は示されていません。コントラクトは具象クラスである必要がありますか?
編集:Richard Blewett によるこの例では、 C# リフレクション - 彼はもっと単純な実装を使用しています。
契約:
public interface IPlugIn
{
// do stuff
}
プラグイン:
public class PlugIn : MarshalByRefObject, IPlugIn
{
}
現在、抽象クラスをコントラクトとして使用している場合、プラグインはコントラクトと MBRO の両方を継承できません。では、スケーラブルなプラグイン フレームワークの最適な実装は何でしょうか。当初は単一マシン操作向けに開発していても、リモート処理を実装する必要がありますか?このプロジェクトは、ネットワーク全体、おそらくインターネット全体に分散されることが予想されます。プラグイン フレームワークの基本を完全に理解して運用できるようにしようとしているため、まだ Tcp を実装していないだけです。
ループバックを使用して単一マシンに Tcp リモート処理を実装することは意味がありますか?
解決
抽象クラスは、このためのより良い選択肢は、私見です。その主なインタフェースは、バージョンに困難ですので。 あなた自身を見つけるかもしれない問題について説明するこのブログ記事あなたが基底クラスを使用していない場合は、道路を下りました。この規則は、ところで、プラグインには適用されないだけではなくています。
あなたのデザインについて...
プラグインはMBROを拡張するべきではありません。あなたはマーシャルにプラグインイベントを処理するなど、あなたのプラグインの間のすべてのコールを、(MBROを拡張する必要があります)あなたのホストを使用する必要があります。その非常に簡単で、あなたは全体のそれらを引くとそのプロキシを使用しようとすると、意図せずに、あなたのメインのAppDomainにプラグインDLLをロードします。
プラグインは、その方法の一つのためのIEnumerableを返す場合、は、例えば、それは、アセンブリのプラグインで定義されてIEnumerableの実装を返すことができます。それはMBROを延長しない場合は、メインのAppDomainは、アセンブリのプラグインをロードする必要があります。
<時間>私はここでのAppDomainを扱う3つのプロジェクトをアップロードしました
一つは、アプリケーションドメインを横切ってコールバックを使用して、第二クロスアプリケーションドメインイベント処理であり、第3は、プラグインの一例である。
は、プラグインの例では、アプリケーションは、プラグインインターフェイス(そのデモではなく、ベストプラクティス!)とプラグインのホストを定義します。アプリ負荷ディスクから組み立て生プラグインと、それがロードされたプラグインホストプロキシを介してプラグインアプリケーションドメインにそれを上を通過します。プラグインのホストは、プラグインをインスタンス化し、それを使用しています。ホストはアセンブリバックを超えるアプリケーションのAppDomainへのプラグインで定義された型を返す場合でも、このプラグインは、アセンブリ全体のプラグインの事の無意味なレンダリング、メインのアプリケーションドメインにロードされます。
はこれを避けるための最善のことは、直列化可能マークされていないとMBROを拡張していないプラグインの抽象基本クラスを提供し、唯一のバックプリミティブまたは密封されたタイプを持ってあなたは、プラグインのドメインから背中境界を越えて定義されます。
注:のプロジェクトはすべて4.0 RCです。あなたはこれが必要でしょうか上記のそれらを実行します。そうしないとあなたが手で編集したプロジェクトファイルを持っているか、それらがB2または2008で実行して取得するためにそれらを再構築します。
他のヒント
は上記のコードは動作する必要があり、完全な型名である。
あなたは、独自のAppDomainに分離され、このタイプを維持しようとしている場合は、しかし、あなたはここで注意しなければなりません。 data.Assembly
を行うことで、あなたはタイプが実行のAppDomain ...
あなたは MAF(マネージドアドインフレームワーク)を見てみたいことがありのアドインを行うため、.NETに組み込まれた拡張フレームワークです。これは MEF(マネージド拡張フレームワーク)のより同様の(およびそれ以前)ですが、保管限りより多くのオプションを持っていますとりわけ、独自のアプリケーションドメインでプラグイン、。
data.EntryPoint.FullName
は、コンクリート型myPlugin
を参照している場合、私はいかなる理由が表示されない理由は、この希望ではない仕事(しない限り、組み立て有する他のAppDomainに問題をロードするが、それは別の問題だより)。