令我感到非常惊讶的是,这个问题并未在每个 IoC/MVVM 教程中涵盖,所以希望我遗漏了一些明显的东西。
简而言之,我的问题是:如何将 Autofac LifeTimeScope 与 ViewModel 的生命周期相关联。
考虑下面的简单应用。
-------------------------------------------------
| _ o x |
-------------------------------------------------
| | |
| Item A | |
| Item B | DetailView for Item A |
| Item C | |
| | |
|------------------------------------------------
此应用程序包含五个 View :
- 主视图
- ListView
- ADetailView
- BDetailView
- CDetailView
以及五个 View 模型
- 主视图模型
- ListView 模型
- ADetalViewModel
- BDetalViewModel
- CDetalViewModel
主视图的结构类似于这样。
<Grid Margin="5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*"></ColumnDefinition>
<ColumnDefinition Width="5"></ColumnDefinition>
<ColumnDefinition Width="2*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListView Grid.Column="0">
</ListView>
<GridSplitter Grid.Column="1"/>
<Border Grid.Column="2">
<Border.Resources>
<DataTemplate DataType="{x:Type vm:ADetailViewModel}">
<vw:ADetailView></vw:ADetailView>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:BDetailViewModel}">
<vw:BDetailView></vw:BDetailView>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:CDetailViewModel}">
<vw:CDetailView></vw:CDetailView>
</DataTemplate>
</Border.Resources>
<ContentPresenter Content="{Binding CurrentDetailViewModel}"></ContentPresenter>
</Border>
</Grid>
因此它是一个模板驱动用户界面,其中模板类型将触发对正确 View 的更改。为此,我们必须实例化正确类型的 ViewModel 并将其分配给 MainViewModel 中的 CurrentDetailViewModel。
现在我到了这个问题。我非常希望创建这个详细 View 模型也能触发 LifetimeScope 的创建。然后它的所有依赖项都将驻留在这个范围内,并且可以在切换到另一个 View / View 模型时轻松处理。
这一定是 Autofac 的一个非常非常非常常见的用例,我很好奇其他人是如何处理它的。
最佳答案
我会将我当前的方法添加到答案列表中,希望有人会添加或给出更好的答案。
我使用了 Owned。当容器找到声明为 Owned<>
的东西时它将在自己的新生命周期范围内创建实例。然后,任何依赖项(默认情况下)也会在此生命周期范围内结束。 lifetimescope 必须通过调用 Dispose()
手动销毁。 .在下面的示例中,我将 Owned 与 Func 结合起来以获得一个用于创建任意数量的拥有实例的工厂。
构造函数:
private readonly Func<Owned<ADetailViewModel> _aFactory;
private readonly Func<Owned<BDetailViewModel> _bFactory;
private readonly Func<Owned<CDetailViewModel> _cFactory;
private IDisposable _currentOwned;
public MainViewModel(Func<int, Owned<ADetailViewModel>> aFactory,
Func<int, Owned<BDetailViewModel>> bFactory,
Func<int, Owned<CDetailViewModel>> cFactory)
{
_aFactory= aFactory;
_bFactory= bFactory;
_cFactory= cFactory;
}
切换细节 View 命令:
private RelayCommand<IListItemViewModel> _switchDetailViewCommand ;
public RelayCommand<IListItemViewModel> SwitchDetailViewCommand
{
get
{
return _switchDetailViewCommand ?? (_switchDetailViewCommand = new RelayCommand<IListItemViewModel>(
(listitem) =>
{
if (_currentOwned != null)
{
_currentOwned.Dispose();
}
switch (listitem.Type)
{
case "A":
{
var aOwned = _aFactory();
_currentOwned = aOwned;
CurrentDetailViewModel = _aOwned.Value;
break;
}
case "B":
{
var bOwned = _bFactory();
_currentOwned = bOwned;
CurrentDetailViewModel = _bOwned.Value;
break;
}
case "C":
{
var cOwned = _cFactory();
_currentOwned = cOwned;
CurrentDetailViewModel = _cOwned.Value;
break;
}
default:
{
break;
}
}
}
));
}
}
关于wpf - Autofac:将 LifeTimeScope 与 MVVM 中 ViewModel 的生命周期相关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37549461/