65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 DDay.MVC 管理您的 Model-View-Controller 应用程序

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.11/5 (5投票s)

2009 年 3 月 5 日

BSD

6分钟阅读

viewsIcon

21684

downloadIcon

166

本文介绍如何使用 DDay.MVC 简化应用程序中的 Model-View-Controller 实现。

为什么选择 Model-View-Controller? 为什么还要费心? 

Model-View-Controller 架构已经存在了几十年,并且仍然是开发敏捷且具有前瞻性应用程序的成熟方法。 它有许多好处,包括: 

  1. 分离
    • 应用程序逻辑 (Controller)  
    • 数据 (Model) 
    • 用户界面 (View)
  2. 可以交换/替换视图和模型。  
    • 是否曾经编写过一个您也想为其提供 Web 界面的 Windows 应用程序?
    • 是否曾想改变数据的存储方式(例如,文件/数据库/XML)。
  3. 正确地将职责委派给应用程序的不同区域。
    • 您的用户界面不应包含应用程序逻辑。 
    • 您的模型不应包含应用程序逻辑。
    • 您的用户界面不应直接修改数据。
    • 等等。
  4. 促进依赖注入(也称为依赖倒置)。

好处远不止这些。 MVC 还会给您的应用程序带来相当大的复杂性,因此在使用它处理小型应用程序时要小心,因为 MVC 的好处可能不值得您付出这些复杂性。

DDay.MVC 

DDay.MVC 是一个库,旨在帮助开发人员利用这些好处,而无需每次手动编写许多特定细节。 DDay.MVC 库负责管理您的 Models、Views 和 Controllers,并将它们连接起来。 

下图显示了 DDay.MVC 中使用的应用程序结构:  

MVC.png

DDay.MVC 还提供了一些规则强制执行功能,可以防止开发人员违反一些基本的 MVC 规则。 如图所示,模型不应能直接访问视图。 正确设置后,DDay.MVC 会强制执行此规则。

规则  

可以从上图得出一些规则: 

  • GUI 绝不能直接与 Controller 交互。
  • GUI 绝不能对 Model 进行更改(例如,保存/删除数据);这必须通过 Controller 进行。
  • GUI 只能通过 View “执行操作”。 
  • GUI 不应自行执行重要的应用程序逻辑 - 这留给 Controller。 它只应执行与通过 GUI 与用户交互直接相关的逻辑。
  • GUI 应通过 View 向 Controller “发出请求”。 Controller 可以满足这些请求,或者选择执行它认为合适的任何操作,包括拒绝请求。
  • GUI 可以对 Model 执行只读查询,以便显示其正确与用户交互所需的信息。
  • GUI 可以通过使用 Model 和 View 公开的事件来检测数据更改。
  • View 绝不能对 Model “执行操作”。
  • Model 绝不能对 View “执行操作”。 

列表还在继续,但我们这里的内容对于我们的目的来说已经足够了。 遵循这些规则很重要,因为它维护了应用程序的整体完整性。 它还确保您可以正确地增强您的应用程序,而不会陷入困境。 这就是 DDay.MVC 发挥作用的地方。

使用代码

从现在开始,我将引用本文示例 MVC 中包含的代码。

本文很难涵盖大部分代码。  至少,大多数人都会在结尾睡着。 所以,为了保持“简洁明了”,我将略过重点,让您自己去探索其余的代码。    

另外,当您自己实现时,您需要从 SourceForge.net 获取最新版本的 DDay.MVC。  

项目用途 

您可能首先注意到的就是包含的各种项目。 每个项目都有其特定用途,如果理解了这些用途,可能有助于您更好地理解应用程序的整体结构:    

  • Application.Console - 应用程序的控制台版本 
  • Application.WinForms - 应用程序的 Windows Forms 版本
  • BusinessObjects - 包含业务对象类(例如,Customer
  • Controller - 包含应用程序的控制器。 这是重要的应用程序逻辑发生的地方。 
  • Model - 包含应用程序的模型定义。 请注意,这里没有具体的模型。 
  • Model.DB - 包含一个(假的)数据库模型。 它包含从数据库保存/检索信息的具体模型。 
  • View - 包含应用程序的视图定义。 一些具体的视图相当通用,可以放在这里(例如,CustomerView)。 其他视图特定于 GUI 实现,并放置在其他程序集中(例如,MainView)。 
  • View.Console - 包含特定于控制台应用程序的具体视图(例如,MainView)。   
  • View.WinForms - 包含特定于 WinForms 应用程序的具体视图(例如,MainView),以及 WinForms 应用程序使用的 GUI 元素(例如,MainFormAddNewCustomerForm 等)。 

依赖注入

如果您查看 BusinessObjects 项目,您可能会注意到的第一件事是几乎每个类都有一个相应的接口。 如果您熟悉这种做法,您可能已经很好地理解了它的重要性。 如果您不熟悉,我建议阅读 Martin Fowler 的这篇文章,其中演示了依赖注入是多么有益。   

您还会注意到在 ModelModel.DB 中,接口和相应的具体类被放在了不同的程序集中。 这并非必需,但有助于组织代码和确定程序集依赖关系。 它还有助于保持应用程序的模块化。 

MVCManager

您可能很快会注意到的另一件事是 MVCManager。 MVCManagerDDay.MVC 的核心。 它包含您所有的模型和视图,并且可以在您需要时检索它们。   

例如,代码使用一个名为 CustomerModel 的模型来存储和检索客户。 如果您想检索客户列表,只需执行以下操作:

// Get the MVCManager for our current process
IMVCManager mvcManager = MVCManager.Current;  

ICustomerModelReadonly customerModel = 
	mvcManager.GetModel<ICustomerModelReadonly>(MVCNames.Customer);
long[] customerIDs = customerModel.GetAllCustomers();
// customerIDs now contains a list of IDs for each customer

List<ICustomer> customers = new List<ICustomer>();
foreach (long id in customerIDs)
    customers.Add(customerModel.GetCustomerByID(id));

如前所述,MVCManager 还强制执行 MVC 规则。 

事件连接   

如果您查看 CustomerController,您会注意到用于连接和断开事件的方法。 这些方法会在 Views/Models 更改时自动调用,并确保 Controller 与 Views/Models 之间的通信线路设置正确。

WireupXXX() 方法中,您需要订阅 Model 或 View 触发的任何您感兴趣要处理的事件。 来自 View 对 Controller 的任何请求都应以这种方式处理。 相反,您需要在 TeardownXXX() 方法中取消订阅事件。 这可以防止出现被错误触发的事件处理程序(这在过去曾给我带来很多麻烦)。 

反馈 

如果您想发布 bug/功能请求,请使用 Sourceforge 项目页面。 我很感激任何人愿意提供的帮助。

附加说明 

本文写于 2009 年 2 月,基于 DDay.MVC 的 0.84 版本。 自那时以来,情况可能已发生重大变化,因此请务必查看 Sourceforge 项目以获取更新,因为您遇到的任何 bug 可能已经在最新版本中得到修复。 

© . All rights reserved.