wpf - Autofac:将 LifeTimeScope 与 MVVM 中 ViewModel 的生命周期相关联

标签 wpf mvvm autofac

令我感到非常惊讶的是,这个问题并未在每个 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/

相关文章:

WPF - 必须满足哪些条件才能在自定义控件的内容项中使用数据绑定(bind)?

WPF 多行 TextBlock 中心对齐问题

c# - 当我的 Model 和 ViewModel 完全相同时,我是否需要使用 MVVM? WP 8.1

c# - 为什么 AutoFac 的 AsImplementedInterfaces 在另一种类型上会破坏我的解析器?

c# - 方法注入(inject)(DI、.NET、IOC)

c# - 如何从后面的代码访问数据模板中的控件?

c# - 在 WPF 应用程序中使用等待

c# - MVC 4 Autofac 和通用存储库模式

C# MVC 4 ViewModel 不接受空 DateTime

c# - "Attribute ' 依赖 ' is not valid on this declaration type."错误