Caliburn.Micro 2.0.2 中 DisplayRootViewFor 调用 GetAllInstances 覆盖时出现异常

Exception when DisplayRootViewFor calls GetAllInstances override in Caliburn.Micro 2.0.2

我正在使用 Caliburn.Micro 2.0.2 和默认的 MEF(托管可扩展性框架)IoC 容器配置。

我正在请求使用 IoC.GetAll 实现特定接口的 ViewModel 集合(是的,我最终要删除 ServiceLocator 反模式)。

上述所有 ViewModel 都使用 [Export(typeof(ISupportFeatureX))] 属性进行修饰。

在 OnStartup() 中加载默认视图之前,一切都按预期工作。出于某种原因,调用了 GetAllInstances() 而不是 GetInstance() 并且我得到了一个异常。

"Could not locate any instances of contract <Namespace>.Views.ShellView."

我的CaliburnBootstrapper如下:

public class CaliburnBootstrapper : BootstrapperBase
{
    CompositionContainer container;

    public CaliburnBootstrapper() { this.Initialize(); }


    void ConfigureIocContainer()
    {
        try
        {
            var catalog = new AggregateCatalog(AssemblySource.Instance.Select(x => new AssemblyCatalog(x))
                                                             .OfType<ComposablePartCatalog>());
            this.container = new CompositionContainer(catalog);

            var batch = new CompositionBatch();

            var eventAggregator = new EventAggregator();
            var windowManager = new WindowManager();

            batch.AddExportedValue<IWindowManager>(windowManager);
            batch.AddExportedValue<IEventAggregator>(eventAggregator);

            batch.AddExportedValue(this.container);
            batch.AddExportedValue(catalog);

            this.container.Compose(batch);
        }
        catch (Exception e)
        {
            this.logger.Error(e);
            throw;
        }
    }
}


    protected override void BuildUp(object instance)
    {
        this.container.SatisfyImportsOnce(instance);
    }

    protected override IEnumerable<object> GetAllInstances(Type serviceType)
    {
        var contract = AttributedModelServices.GetContractName(serviceType);
        var exports = this.container.GetExportedValues<object>(contract);

        if (exports.Any()) return exports;

        throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
    }


    protected override object GetInstance(Type serviceType, string key)
    {
        var contract = string.IsNullOrEmpty(key) ? AttributedModelServices.GetContractName(serviceType) : key;
        var exports = this.container.GetExportedValues<object>(contract);

        if (exports.Any()) return exports.First();

        throw new Exception(string.Format("Could not locate any instances of contract {0}.", contract));
    }

    protected override void OnStartup(object sender, StartupEventArgs e)
    {
        this.DisplayRootViewFor<IShellViewModel>();
    }

我的视图和视图模型在不同的项目中,因此 SelectAssemblies 覆盖。

    protected override IEnumerable<Assembly> SelectAssemblies()
    {
        var assemblies = new List<Assembly>();
        assemblies.Add(typeof (IShellViewModel).Assembly);
        assemblies.Add(typeof (ShellView).Assembly);
        return assemblies;
    }

在我重写 GetAllInstances() 之前,该应用程序在此 Caliburn.Micro 设置下运行良好。查看 Caliburn.Micro 源代码,我在 DisplayRootViewFor() 调用链中看不到对 GetAllInstances() 的任何调用。

关于为什么 GetInstance() 解析 ShellView 但 GetAllInstances() 中的相同代码没有解析的任何解释?

Caliburn.Micro (CM) 的默认行为是为您实例化我们的视图。覆盖 "GetAllInstances" 后,CM 不再为您创建视图实例,而是从容器中查找对象。

由于视图未注册到容器(在本例中,使用 MEF [Export] 属性),因此当在容器中找不到请求的视图时,GetAllInstances 调用会抛出异常。

这是一个不了解 Caliburn.Micro 和作为 IoC 容器的 MEF 内部结构的简单问题。