我很惊讶每个IoC / MVVM教程都没有涵盖这个问题,所以希望我遗漏了一些明显的问题。
简而言之,我的问题是:如何将Autofac LifeTimeScope与ViewModel的生命周期联系起来。
考虑下面的简单应用程序。
-------------------------------------------------
| _ o x |
-------------------------------------------------
| | |
| Item A | |
| Item B | DetailView for Item A |
| Item C | |
| | |
|------------------------------------------------
此应用程序包含五个视图:
以及五个视图模型
主视图的结构类似于此。
<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>
因此它是一个模板驱动器用户界面,其中模板类型将触发更改正确的视图。为此,我们必须实例化一个正确类型的ViewModel,并将其分配给MainViewModel中的CurrentDetailViewModel。
现在我到了这个问题。我非常喜欢创建这个细节视图模型来触发LifetimeScope的创建。然后,它的所有依赖项都将驻留在此范围内,并且在切换到另一个视图/视图模型时可以轻松处理。
这对于Autofac来说是一个非常常见的用例,我很好奇其他人如何接近它。
答案 0 :(得分:0)
我会将当前的方法添加到答案列表中,希望有人会添加或给出更好的答案。
我利用了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;
}
SwitchDetailViewCommand:
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;
}
}
}
));
}
}