我在使用Caliburn.Micro框架的WPF中使用MEF作为IoC容器。 MEF容器位于Bootstrapper
。 Bootstrapper
的方法有:
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<ViewModels.Main.MainViewModel>();
}
现在,MainViewModel
有这个:
private IEnumerable<ExportFactory<Screen>> _screenList { get; set; }
[ImportingConstructor]
public MainViewModel(IEventAggregator eventAggregator, [ImportMany] IEnumerable<ExportFactory<Screen>> screenList)
{
_screenList = screenList;
eventAggregator = eventAggregator;
_eventAggregator.Subscribe(this);
}
该课程基本上有IEnumerable
ExportFactory
。 Screen
基本上是ViewModel
,继承自VMBase
,Screen
继承自ViewModel
。现在,其中一些DbContext
使用工作单元,而工作单元又通过constructor
注入了DbContext -> UnitOfWork (IDisposable) -> ViewModelBase(IDisposable) -> ViewModels
。
所以基本上,依赖链是这样的:
ViewModel
。这些ExportFactory
使用MainViewModel
中的MainViewModel
进行实例化。
eventAggregator
订阅Handler
,而MainViewModel
ExportFactory
调用ViewModel
来创建ViewModel
的新实例有必要的。问题是,当DbContext
关闭时,Handle
未正确处理。
这是public void Handle(Type message)
{
DeactivateItem(ActiveItem, true);
ActivateItem(screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport().Value);
}
方法:
DbContext
这会创建Dispose()
的新实例,但不会调用ViewModelBase
的{{1}},因为我使用断点进行了验证。
我尝试更改Handle
方法,以便像这样调用Dispose()
:
DeactivateItem(ActiveItem, true);
_currentLifetimeContext?.Dispose();
_currentLifetimeContext = _screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport();
ActivateItem(_currentLifetimeContext.Value);
但它会抛出一个错误“无法完成操作,因为已经处理了DbContext。”
如何在我的应用程序中正确处理DbContext
?
答案 0 :(得分:1)
几乎不可能在没有完整测试的情况下说明代码失败的原因。但是,由于我对MEF的经验有限,我发现当导出未明确标记为NonShared
时,会产生大多数处理问题。这是MEF的烦恼之一,默认情况下它将所有组件视为单例。我的建议是明确标记你的每个导出为NonShared
,除非你想要一个单身人士。不只是ViewModels
。如果有效,请告诉我们。