日期:2010-08-21 浏览次数:20488 次
模型-视图-控制器分离的重构
为了解决上面所遗留的问题,你必须将模型与控制器角色分离。
视图的实现代码与前部分相同。
模型
下面的代码例子使模型角色仅仅依赖于数据库,而不包含任何与视图相依赖的代码。
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
public class DatabaseGateway
{
public static DataSet GetRecordings()
{
String selectCmd = "select * from Recording";
SqlConnection myConnection =
new SqlConnection(
"server=(local);database=recordings;Trusted_Connection=yes");
SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);
DataSet ds = new DataSet();
myCommand.Fill(ds, "Recording");
return ds;
}
public static DataSet GetTracks(string recordingId)
{
String selectCmd =
String.Format(
"select * from Track where recordingId = {0} order by id",
recordingId);
SqlConnection myConnection =
new SqlConnection(
"server=(local);database=recordings;Trusted_Connection=yes");
SqlDataAdapter myCommand = new SqlDataAdapter(selectCmd, myConnection);
DataSet ds = new DataSet();
myCommand.Fill(ds, "Track");
return ds;
}
现在的代码只依赖于数据库,这个类是一个优秀的数据库的通道,它持有访问表或视图的所用的SQL语句,其它的代码调用一些方法来完成与数据库的交互。
控制器
这种重构方式利用代码隐藏机制,在负责数据访问的模型部分相对独立的情况下,由控制器负责事件与方法的控制工作。模型的任务很明确的,它仅返回一个DataSet对象。这种实现方式就像视图代码一样,不依赖于数据是如何从数据库中返回的。
using System;
using System.Data;
using System.Collections;
using System.Web.UI.WebControls;
public class Solution : System.Web.UI.Page
{
protected System.Web.UI.WebControls.Button submit;
protected System.Web.UI.WebControls.DataGrid MyDataGrid;
protected System.Web.UI.WebControls.DropDownList recordingSelect;
private void Page_Load(object sender, System.EventArgs e)
{
if(!IsPostBack)
{
DataSet ds = DatabaseGateway.GetRecordings();
recordingSelect.DataSource = ds;
recordingSelect.DataTextField = "title";
recordingSelect.DataValueField = "id";
recordingSelect.DataBind();
}
}
void SubmitBtn_Click(Object sender, EventArgs e)
{
DataSet ds =
DatabaseGateway.GetTracks(
(string)recordingSelect.SelectedItem.Value);
MyDataGrid.DataSource = ds;
MyDataGrid.DataBind();
}
#region Web Form Designer generated code
override protected void OnInit(EventArgs e)
{
//
// CODEGEN: This call is required by the ASP.NET Web Form Designer.
//
InitializeComponent();
base.OnInit(e);
}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.submit.Click += new System.EventHandler(this.SubmitBtn_Click);
this.Load += new System.EventHandler(this.Page_Load);
}
#endregion
}
测试
将模型部分从ASP.NET环境中分离出来能够使模型部分更容易的被测试。在ASP.NET环境中进行测试的话,你必须同时测试很多方面,如HTML代码是否正确,而读取HTML代码的工作是非常烦闷的。将模型部分分离出来,使你能够对模型部分做单独的单元测试。下面是NUnit (http://nunit.org)对模型部分进行单元测试的例子。
using System;
using NUnit.Framework;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
[TestFixture]
public class GatewayFixture
{
[Test]
public void Tracks1234Query()
{
DataSet ds = DatabaseGateway.GetTracks("1234");
Assertion.AssertEquals(10, ds.Tables["Track"].Rows