MEF2 を使用して簡単なプラグイン システムを作成しようとしています。
私のシナリオでは、プラグインは 1 ~ 10 個しかないため、パフォーマンスの問題を回避するために別のドメインにアセンブリをロードすることを気にしないことにしました。とにかくこれはいいことですが、エクスポートされたオブジェクトにいくつかの制約を課しているようです ([Serializable]
から派生する必要があります: https://msdn.microsoft.com/en-us/library/ms972968.aspxおよびhttp://wwwMarshalByRefObject
を参照) .codeproject.com/Articles/1091726/The-Nuances-of-Loading-and-Unloading-Assemblies-wiおよびhttps://msdn.microsoft.com/en-us/magazine/jj133818.aspx )、そして私はそれらが必要ですソースを制御できないため、POCOオブジェクトになります。
特定のインターフェイスから派生した型をエクスポートするすべてのアセンブリをロードする必要があるだけなので、ディレクトリをスキャンしてアセンブリを収集し、T から派生したすべての型をエクスポートする規則で構成された MEF2 コンテナーを返すことができる単純なカタログ クラスを作成しました (下)。
とにかく、それを使用しようとすると、コンテナー アセンブリが正しく検出されて読み込まれたとしても、カタログにエクスポートを含めることができません。確かに、MEF2エクスポート規則に何かが欠けています。誰かが私に解決策を教えてもらえますか?
https://onedrive.live.com/redir?resid=F8DEF93587EC2C1!258076&authkey=!AKSKUhMwFhV0n-k&ithint=file%2czipで完全なダミーの再現ソリューションを見つけることができます。
関連するコードと使用例は次のとおりです。
public sealed class PluginCatalog<T>
{
private readonly string _sFileMask;
private readonly List<Assembly> _aAssemblies;
private bool _bLoaded;
public string SourceDirectory { get; }
public bool IsRecursive { get; }
public PluginCatalog(string directory, string fileMask = "*.dll", bool recursive = false)
{
_aAssemblies = new List<Assembly>();
_sFileMask = fileMask;
SourceDirectory = directory;
IsRecursive = recursive;
}
private void LoadPluginAssemblies(string directory)
{
if (directory == null) throw new ArgumentNullException(nameof(directory));
// scan DLLs
foreach (string sFilePath in Directory.GetFiles(directory, _sFileMask))
{
Assembly asm = Assembly.LoadFrom(sFilePath);
if (asm.GetTypes().Any(typeof(T).IsAssignableFrom)) _aAssemblies.Add(asm);
}
// scan subdirectories if required
if (IsRecursive)
{
foreach (string sSubdir in Directory.GetDirectories(directory))
LoadPluginAssemblies(sSubdir);
}
_bLoaded = true;
}
public CompositionHost GetContainer()
{
if (!_bLoaded) LoadPluginAssemblies(SourceDirectory);
// export all the types implementing the requested interface type
ConventionBuilder builder = new ConventionBuilder();
builder.ForTypesMatching(t => typeof(T).IsAssignableFrom(t)).Export<T>();
// create the container from all the plugins assemblies
return new ContainerConfiguration()
.WithAssemblies(_aAssemblies)
.CreateContainer();
}
}
使用例:
PluginCatalog<IAnimal> catalog = new PluginCatalog<IAnimal>(directoryName, "*Plugin*.dll");
CompositionHost container = catalog.GetContainer();
var animals = container.GetExports<IAnimal>().ToList();