1

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();
4

0 に答える 0