视图模型和依赖注入

本文关键字:注入 依赖 模型 视图 | 更新日期: 2023-09-27 17:50:24

在使用PRISM和Enterprise Library处理带有大量CRUD操作的LOB桌面应用程序时,我注意到一个反复出现的模式似乎很烦人。对于每个领域模型实体(例如。我发现我自己包装它与视图模型(例如。ContactVM),然后我引入一个新的ContactsVM(注意's'),其中后一个类接受一个存储库接口,用于填充ObservableCollection<ContactVM>,对于我从存储库中读取的每个Contact实体,我将其包装在ContactVM中,我通过构造函数将实体传递给我的ViewModel所需的其他企业库服务。

问题是我所有的视图模型构造器都开始采用这种模式:

ViewModel(EntityToWrap e, DependencyFromEntLib, OtherDependencies ...)

现在这是一个问题,因为大多数工具和库都需要默认的无参数构造函数(例如:一些商业数据网格需要它来提供过滤支持),另外您不能使用设计数据来可视化实体,因为它们也需要无参数构造函数。最后的问题是:构建视图模型的正确方法是什么? Entlib服务应该通过构造函数还是通过ServiceLocator提供?

视图模型和依赖注入

下面是解决这个问题的多种方法之一。

我更喜欢轻量级得多的视图模型。然后我添加一个类,它的职责是从一个或多个源(例如存储库)组合视图模型。这并不能消除级联依赖的问题,但它确实释放了视图模型构造器。

它还使逻辑远离控制器,并允许视图模型被重用(当然,在适当的时候)。

  • 轻量级视图模型

  • 轻量级控制器知道如何定位组装视图模型的编写器(您可以使用DI框架来设置包含所有依赖项的编写器)。控制器可能在设置过程中起次要作用,但应该保持简单。

  • 控制器知道视图模型应该如何组装,并与编写器类共享。例如,该操作可能请求一个摘要视图,该视图仍然可以利用没有填充子视图的相同视图模型。

  • Composer组装必要的信息来完成视图模型。作曲家可以使用其他作曲家收集信息,而不是直接负责。同样,可以在这里使用DI框架,这样这些作曲家也可以获得他们需要的依赖项。

  • 控制器以完成的视图模型像往常一样渲染视图。

在我看来,这也提供了一个更好的抽象层次。仅仅因为一个视图模型经常看起来像一个特定的域模型,这并不意味着它总是这样。

最终结果:

  • 大量的类(一个缺点,承认),但最少的代码重复(即DRY)

  • 瘦视图模型是可测试的(如果需要…

  • 可测试的瘦控制器

  • 可测试的编写器对象,可以在不同的场景中重用,因为它们(大概)知道如何为各种目的组装视图模型。

  • 灵活地混合和匹配视图模型、控制器和作曲家,以支持不同的场景。