こんにちは、私はメタデータ属性を検出する MEF コンテナーを持っています。これを拡張して、クラスが追加のインターフェイスを実装できるようにしたいと考えています (以下の例では、追加のインターフェイス IPluginSettings を実装したいと考えています)。
モジュール GUID 識別子は、データベース アプリケーションのモジュール ID と調整されるため、重要です。インポートされたインターフェイスの MEF コンテナーをクエリすると、それらをループできます。
foreach (Lazy<T,IPluginMetadata> moduleInAssembly in m_Container.GetExports<T, IPluginMetadata>();)
{
T value = moduleInAssembly.Value; // instantiate an object of type T to test for implementations of other interfaces...
if (value is IPluginSettings)
{
// this module also contains an interface for settings!
}
Guid moduleInAssemblyId = Guid.Parse(moduleInAssembly.Metadata.PluginID);
}
いくつか質問があります:
1) 上記のシナリオでは、特定のインターフェイスを実装しているかどうかをテストするためにクラスをインスタンス化する必要があります。メタデータでこれを行い、PluginExportAttribute を拡張してセカンダリ インターフェイス タイプのリストを受け入れるより良い方法はありますか?
2) MEF コンテナーに、PluginExportAttribute のみを持つ型をインポートするように指示するにはどうすればよいですか?
3) または、各プラグイン インターフェイスに独自のインターフェイスを柔軟に/自由に宣言させる代わりに、特定のプラグイン インターフェイスをインスタンス化するためのファクトリを含む既知のプラグイン インターフェイスをプラグインに実装する方がよいでしょうか? (私が求めている例は、コードの下部にあります - 最後のセクション)
4) 提案された 1 つの回答のおかげで、以下の質問 4 のスニピットに従って構造化されたコードを使用しています。好奇心から、登録する追加のタイプのリストを取得するために、おそらくコンストラクターパラメーターで、複数の個別のエクスポート属性を PluginExportAttribute にマージする方法はありますか?
ありがとう、
クリス
public interface IPluginMetadata
{
string PluginID { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginExportAttribute : ExportAttribute, IPluginMetadata
{
public PluginExportAttribute(Type t, string guid)
: base(t)
{
PluginID = guid.ToUpper();
}
public string PluginID { get; set; }
}
[PluginExport(typeof(IAccountsPlugin),"BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public class BillingModule : IAccountsPlugin, IPluginSettings
{
// my class contents
}
それとも私はこのようなことをした方が良いでしょうか...?
// or would i be better of by implementing a plugin base, and getting instances of the plugin via a secondary factory?
public interface IWellKnownPluginBase
{
Guid PluginID { get; }
Version Version { get; }
IPluginSettings Settings { get; }
Type GetPluginInterfaceType { get; }
object PluginInterfaceFactory();
}
public interface IMyPlugin
{
void DoSomethingCool();
}
[Export(typeof(IWellKnownPluginBase))]
public class MyPluginWrapper : IWellKnownPluginBase
{
private readonly string ID = "BE112EA1-1AA1-4B92-934A-9EA8B90D622C";
Guid PluginID { get { return Guid.Parse(ID); } }
Version Version { get {return new Version(1,0,0); } }
IPluginSettings Settings { get { return new SomethingThatImplementsIPluginSettings(); }
Type GetPluginInterfaceType { get { return gettype(IMyPlugin); }
object PluginInterfaceFactory() { return new MyPlugin(); }
class MyPlugin : IMyPlugin
{
void DoSomethingCool() {}
}
}
質問 4 - PluginExport を書き直して、複数のインターフェースをコンストラクターのインターフェースのリストに登録できますか?
[Export(typeof(IPluginSettings))]
[PluginExport(typeof(IAccountsPlugin),"BE112EA1-1AA1-4B92-934A-9EA8B90D622C")]
public MyModule class : IModule, IPluginSettings
{
}