MEF ExportFactory 不处理 IDisposable ViewModels
MEF ExportFactory does not dispose of IDisposable ViewModels
我在 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);
}
class 基本上有一个 IEnumerable
的 ExportFactory
。 Screen
基本上是继承自 VMBase
的 ViewModel
,后者又继承自 Screen
。现在,其中一些 ViewModel
使用工作单元,而工作单元又通过 constructor
.
注入了 DbContext
基本上,依赖链是这样的:
DbContext -> UnitOfWork (IDisposable) -> ViewModelBase(IDisposable) -> ViewModels
。这些 ViewModel
使用 MainViewModel
中的 ExportFactory
实例化。
MainViewModel
订阅eventAggregator
,MainViewModel
的Handler
调用ExportFactory
创建[=20的新实例=] 根据需要。问题是,当 ViewModel
关闭时,DbContext
没有被正确处理。
这是Handle
方法:
public void Handle(Type message)
{
DeactivateItem(ActiveItem, true);
ActivateItem(screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport().Value);
}
这会创建 DbContext
的新实例,但不会调用 ViewModelBase
的 Dispose()
,正如我使用断点验证的那样。
我尝试更改 Handle
方法来调用 Dispose()
,如下所示:
DeactivateItem(ActiveItem, true);
_currentLifetimeContext?.Dispose();
_currentLifetimeContext = _screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport();
ActivateItem(_currentLifetimeContext.Value);
但是它抛出一个错误"The operation cannot be completed because the DbContext has been disposed."
如何正确处理我的应用程序中的 DbContext
?
如果不对代码进行整体测试,几乎不可能说明代码失败的原因。但是,根据我对 MEF 的有限经验,我发现大多数处理问题都是在导出未明确标记为 NonShared
时产生的。这是 MEF 的烦恼之一,它默认将所有组件视为单例。我的建议是将您的每个导出明确标记为 NonShared
,除非您想要一个单例。不仅仅是 ViewModels
。让我们知道它是否有效。
我在 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);
}
class 基本上有一个 IEnumerable
的 ExportFactory
。 Screen
基本上是继承自 VMBase
的 ViewModel
,后者又继承自 Screen
。现在,其中一些 ViewModel
使用工作单元,而工作单元又通过 constructor
.
DbContext
基本上,依赖链是这样的:
DbContext -> UnitOfWork (IDisposable) -> ViewModelBase(IDisposable) -> ViewModels
。这些 ViewModel
使用 MainViewModel
中的 ExportFactory
实例化。
MainViewModel
订阅eventAggregator
,MainViewModel
的Handler
调用ExportFactory
创建[=20的新实例=] 根据需要。问题是,当 ViewModel
关闭时,DbContext
没有被正确处理。
这是Handle
方法:
public void Handle(Type message)
{
DeactivateItem(ActiveItem, true);
ActivateItem(screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport().Value);
}
这会创建 DbContext
的新实例,但不会调用 ViewModelBase
的 Dispose()
,正如我使用断点验证的那样。
我尝试更改 Handle
方法来调用 Dispose()
,如下所示:
DeactivateItem(ActiveItem, true);
_currentLifetimeContext?.Dispose();
_currentLifetimeContext = _screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport();
ActivateItem(_currentLifetimeContext.Value);
但是它抛出一个错误"The operation cannot be completed because the DbContext has been disposed."
如何正确处理我的应用程序中的 DbContext
?
如果不对代码进行整体测试,几乎不可能说明代码失败的原因。但是,根据我对 MEF 的有限经验,我发现大多数处理问题都是在导出未明确标记为 NonShared
时产生的。这是 MEF 的烦恼之一,它默认将所有组件视为单例。我的建议是将您的每个导出明确标记为 NonShared
,除非您想要一个单例。不仅仅是 ViewModels
。让我们知道它是否有效。