Exception when DisplayRootViewFor calls GetAllInstances override in Caliburn.Micro 2.0.2

时间:2015-04-28 20:06:43

标签: c# caliburn.micro

I'm using Caliburn.Micro 2.0.2 with the default MEF (Managed Extensibility Framework) IoC container configuration.

I am requesting a collection of ViewModels that implement a certain interface by using IoC.GetAll<ISupportFeatureX> (Yes, I'm eventually removing the 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>();
    }

我的视图和ViewModel位于不同的项目中,因此SelectAssemblies重写。

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

该应用程序在此Caliburn.Micro设置下工作正常,直到我覆盖GetAllInstances()。查看Caliburn.Micro源代码,我在DisplayRootViewFor()调用链中看不到对GetAllInstances()的任何调用。

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

1 个答案:

答案 0 :(得分:1)

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

由于视图未在容器中注册(在这种情况下,使用MEF [Export]属性),因此在容器中找不到请求的View时,GetAllInstances调用将引发异常。

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