C# MVVM与避免单一God对象

C# MVVM与避免单一God对象,c#,wpf,mvvm,god-object,C#,Wpf,Mvvm,God Object,我正处于一个大型项目的完成阶段,该项目有几个大的组成部分:图像采集、图像处理、数据存储、工厂I/O(自动化项目)和其他几个部分 这些组件中的每一个都是相当独立的,但是为了使项目作为一个整体运行,我需要每个组件至少有一个实例。每个组件还有一个ViewModel和View(WPF),用于监视状态和更改内容 我的问题是实例化所有这些对象、将一个类订阅给另一个类中的一个事件以及为所有这些对象创建一个公共的ViewModel和View的最安全、最有效和最可维护的方法 如果我有一个名为God的类,它有一个所

我正处于一个大型项目的完成阶段,该项目有几个大的组成部分:图像采集、图像处理、数据存储、工厂I/O(自动化项目)和其他几个部分

这些组件中的每一个都是相当独立的,但是为了使项目作为一个整体运行,我需要每个组件至少有一个实例。每个组件还有一个ViewModel和View(WPF),用于监视状态和更改内容

我的问题是实例化所有这些对象、将一个类订阅给另一个类中的一个事件以及为所有这些对象创建一个公共的ViewModel和View的最安全、最有效和最可维护的方法

如果我有一个名为God的类,它有一个所有这些对象的私有实例,这会是最好的吗?我过去做过这件事,但我后悔了

或者,如果上帝依靠这些物体的单个实例来让球滚动,那会更好吗

或者,Program.cs(或Main(…)所在的任何地方)应该实例化所有这些组件,并将它们作为参数传递给上帝,然后让上帝(snicker)和他的ViewModel处理运行此项目的细节

我还想听听其他的建议


谢谢大家!

获取ViewModels的首选方法是使用ViewModelLocater。基本上,它是您所暗示的上帝对象,但它唯一的责任是创建每个ViewModel并保留对它的引用。我通常将VML添加到应用程序的资源中,每个视图负责将其DataContext设置为正确的ViewModel。如果您订阅多个事件,您可以让VML手动将它们连接起来,或者它可以创建首先抛出事件的VM,并将其传递给构造函数中的从属VM。

我希望我已经很好地理解了您的问题。我认为使用God ViewModel不是一个好主意。最好为每个视图使用一个viewmodel,并在该viewmodel中实例化所有相关的viewmodel。然后,您可以使用中介在该视图的视图模型和其他视图之间安全地发送消息。我还建议使用wpf命令而不是事件。您可以在中找到一篇关于mediator的文章。

使用Microsoft的“复合应用程序库”(又称Prism)开发复合WPF应用程序的框架,这些问题得到了很好的解决:

  • 组成视图:Prism有一个应用程序外壳窗口和区域管理器的概念。shell充当一个基本布局页面,您可以在其中定义命名的占位符区域,例如“MainMenu”和“TabInterface”。将视图和视图模型的引用封装在模块类中,例如“MainMenuModule”和“TabInterfaceModule”,并定义模块应与哪个区域关联。Prism将创建您的视图,并在应用程序启动时将它们注入shell区域。这允许您独立地组合视图

  • viewmodels之间的通信:Prism支持称为“事件聚合器”的中介模式。基本上,您可以通过viewmodels中的事件生成器发布和订阅消息。这使得viewmodels可以通过消息进行松散的通信,而不必了解彼此和挂钩事件

Prism提倡并支持以松散耦合的方式独立开发组件的模式,而不引入God对象和过度耦合。Prism的很大一部分还在于它使用了IOC和依赖注入,因此单元测试也变得容易多了

我发现下面的文章是使用Prism和MVVM的一个很好的实用介绍:


看看一些依赖注入框架,例如Unity(CAL使用)、Castle Windsor或Spring.NET。

您可以使用控制器(ApplicationController,用例控制器),而不是“God”类。控制器负责创建ViewModel对象,并在它们之间进行调解


项目展示了这一点。

我已经尝试了每一种非第三方方法,除了最后一种方法外,每一种尝试都在某种程度上失败了,最后确定了一种非常接近您的ViewModelLocater模式的方法。我相信其他人发布的第三方框架会帮我省下很多工作,但我进入项目太晚了。这个答案是一个很好的中间立场。我想你也学了很多。不管怎么说,几个月后我们就到了,但是——谢谢!