对于这个很长的问题,我深表歉意。我在下面总结了我的问题
在MVC世界中,事情很简单。该模型具有状态,在视图显示模式,并且控制器不东西/与模型(基本上),控制器没有的状态。为了完成这些工作,Controller对Web服务,存储库等有一些依赖性。实例化控制器时,您关心的是提供那些依赖关系,而没有别的。执行动作(Controller上的方法)时,可以使用这些依赖关系来检索或更新Model或调用某些其他域服务。如果存在任何上下文,例如说某些用户想要查看特定项目的详细信息,则将该项目的ID作为参数传递给Action。Controller中的任何地方都没有对任何状态的引用。到目前为止,一切都很好。
输入MVVM。我爱WPF,我喜欢数据绑定。我喜欢使数据绑定到ViewModels更加容易的框架(使用Caliburn Micro atm)。我觉得这个世界上事情并不那么简单。让我们再次做运动:该模型具有状态下,查看显示的视图模型和视图模型做的东西/使用模型(基本),一个视图模型做有状态!(澄清;也许它代表所有属性的一个或多个模型,但是这意味着它必须具有对模型的一种方式或另一种,这本身就是状态的基准)为了做ViewModel在Web服务,存储库等方面有一些依赖性。实例化ViewModel时,您关心的是提供那些依赖关系,还需要提供状态。女士们,先生们,这无休止地困扰着我。
每当您需要从中实例化a ProductDetailsViewModel
时ProductSearchViewModel
(您又从中实例化了ProductSearchWebService
which IEnumerable<ProductDTO>
,每个人还和我在一起吗?),您可以执行以下操作之一:
- call
new ProductDetailsViewModel(productDTO, _shoppingCartWebService /* dependcy */);
,这很糟糕,想象另外3个依赖关系,这意味着也ProductSearchViewModel
需要承担这些依赖关系。改变构造函数也是很痛苦的。 - 调用
_myInjectedProductDetailsViewModelFactory.Create().Initialize(productDTO);
,工厂只是一个Func,大多数IoC框架很容易生成它们。我认为这很糟糕,因为Init方法是一个泄漏的抽象。您也不能对Init方法中设置的字段使用readonly关键字。我确定还有更多原因。 - 呼叫
_myInjectedProductDetailsViewModelAbstractFactory.Create(productDTO);
So ...这是通常建议用于此类问题的模式(抽象工厂)。我虽然是个天才,但它满足了我对静态类型的渴望,直到我真正开始使用它为止。我认为样板代码太多了(除了我使用的荒谬变量名之外,您都知道)。对于每个需要运行时参数的ViewModel,您将获得两个额外的文件(工厂接口和实现),并且需要键入非运行时依赖项,例如额外输入4次。而且,每次依赖关系发生变化时,您也需要在工厂中进行更改。感觉我什至不再使用DI容器。(我认为温莎城堡对此有某种解决方案(有其自身的缺点,如果我错了,请纠正我))。 - 用匿名类型或字典来做某事。我喜欢我的静态打字。
是的。以这种方式混合状态和行为会产生一个在MVC中根本不存在的问题。我觉得目前还没有一个真正足够的解决方案来解决这个问题。现在,我想观察一些事情:
- 人们实际上使用了MVVM。因此,他们要么不在乎以上所有内容,要么拥有一些出色的其他解决方案。
- 我还没有找到带有WPF的MVVM的深入示例。例如,NDDD示例项目极大地帮助我理解了一些DDD概念。如果有人可以将我指向类似MVVM / WPF的方向,我真的很喜欢它。
- 也许我在做MVVM时出错了,应该将我的设计倒过来。也许我根本不应该有这个问题。好吧,我知道其他人也问过同样的问题,所以我认为我不是唯一的一个。
总结一下
- 我是否可以正确地得出结论,将ViewModel作为状态和行为的集成点是整个MVVM模式存在某些困难的原因?
- 使用抽象工厂模式是以静态类型实例化ViewModel的唯一/最佳方法吗?
- 是否有类似深度参考实现的内容?
- 是否有很多带有状态/行为的ViewModels设计气味?