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 内部结构的简单问题。
我正在使用 Caliburn.Micro 2.0.2 和默认的 MEF(托管可扩展性框架)IoC 容器配置。
我正在请求使用 IoC.GetAll
上述所有 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 内部结构的简单问题。