C# 两次导入类型会导致MEF失败

C# 两次导入类型会导致MEF失败,c#,mef,C#,Mef,我试图用MEF编写一个小模块系统,因此我有一个基本模块,如下所示: public abstract class Module : IModule { [Import] private IShell _shell; protected IShell Shell { get { return _shell; } } } 还有一些类似的模块: [Export(typeof(IModule))] public class TodoListMod

我试图用MEF编写一个小模块系统,因此我有一个基本模块,如下所示:

public abstract class Module : IModule
{
    [Import]
    private IShell _shell;

    protected IShell Shell
    {
        get { return _shell; }
    }
}
还有一些类似的模块:

[Export(typeof(IModule))]
public class TodoListModule : Module
{

}
如您所见,基本模块依赖于IShell。我有一个这样的实现:

[Export(typeof(IShell))]
public class ShellViewModel : IShell
{
    [ImportMany]
    private IEnumerable<IModule> _modules;

    .... and later...

    private void InitializeModules()
    {
        foreach (var module in _modules)
        {
            // init modules.
        }
    }
}
因此,原因是我们有两个实现通过基类获得IShell。为什么会这样

这是我的容器配置:

        // Add all assemblies to AssemblySource (using a temporary DirectoryCatalog).
        var directoryCatalog = new DirectoryCatalog(@"./");
        AssemblySource.Instance.AddRange(
            directoryCatalog.Parts
                .Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly)
                .Where(assembly => !AssemblySource.Instance.Contains(assembly)));

        // Prioritise the executable assembly. This allows the client project to override exports, including IShell.
        // The client project can override SelectAssemblies to choose which assemblies are prioritised.
        var priorityAssemblies = SelectAssemblies().ToList();
        var priorityCatalog = new AggregateCatalog(priorityAssemblies.Select(x => new AssemblyCatalog(x)));
        var priorityProvider = new CatalogExportProvider(priorityCatalog);

        // Now get all other assemblies (excluding the priority assemblies).
        var mainCatalog = new AggregateCatalog(
            AssemblySource.Instance
                .Where(assembly => !priorityAssemblies.Contains(assembly))
                .Select(x => new AssemblyCatalog(x)));
        var mainProvider = new CatalogExportProvider(mainCatalog);

        container = new CompositionContainer(priorityProvider, mainProvider);
        priorityProvider.SourceProvider = container;
        mainProvider.SourceProvider = container;

        var batch = new CompositionBatch();

        BindServices(batch);
        batch.AddExportedValue(mainCatalog);

        container.Compose(batch);

当任何其他类导入IShell时也会发生这种情况

为什么需要编写?当您处理尝试引用模块的未知对象时,此功能非常好。也许这能帮你。在这里,我描述了批量导入是如何工作的,您可以下载一个能够编写的工作解决方案,IShell是否可能从IModule中导入?如果是这样的话,您可能会在尝试撰写时陷入循环依赖,因为ShellViewModel@JPVensonIShell不继承IModule。配置代码是我为Caliburn.Micro找到的一些引导代码的一部分。我已经有了一个可行的解决方案,但我无法找出有什么不同的做法,因为配置代码就在那里。
        // Add all assemblies to AssemblySource (using a temporary DirectoryCatalog).
        var directoryCatalog = new DirectoryCatalog(@"./");
        AssemblySource.Instance.AddRange(
            directoryCatalog.Parts
                .Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly)
                .Where(assembly => !AssemblySource.Instance.Contains(assembly)));

        // Prioritise the executable assembly. This allows the client project to override exports, including IShell.
        // The client project can override SelectAssemblies to choose which assemblies are prioritised.
        var priorityAssemblies = SelectAssemblies().ToList();
        var priorityCatalog = new AggregateCatalog(priorityAssemblies.Select(x => new AssemblyCatalog(x)));
        var priorityProvider = new CatalogExportProvider(priorityCatalog);

        // Now get all other assemblies (excluding the priority assemblies).
        var mainCatalog = new AggregateCatalog(
            AssemblySource.Instance
                .Where(assembly => !priorityAssemblies.Contains(assembly))
                .Select(x => new AssemblyCatalog(x)));
        var mainProvider = new CatalogExportProvider(mainCatalog);

        container = new CompositionContainer(priorityProvider, mainProvider);
        priorityProvider.SourceProvider = container;
        mainProvider.SourceProvider = container;

        var batch = new CompositionBatch();

        BindServices(batch);
        batch.AddExportedValue(mainCatalog);

        container.Compose(batch);