为了账号安全,请及时绑定邮箱和手机立即绑定

重构ASP.NET程序----继承

标签:
SQL Server

数据库SQL Server 2008 R2,数据名为[Demo],它有四张表[UnitCode1], [UnitCode2], [UnitCode3], [UnitCode4],每个表有几个字段[Unit1~4],[Description],[CreateBy],[CreateDate],[UpdateBy],[UpdateDate],此四个表的主键分别为[Unit1],[Unit2],[Unit3]和[Unit4],其余字段名称四张表都一样。数据库还有各个表的相关的存储过程。

程序中有一个接口,是为了设置网页标题。数据库四张表对应的类别,程序应用了母版,有5个网页,Default.aspx, UnitCode1.aspx, UnitCode2.aspx, UnitCode3.aspx和UnitCode4.aspx 。每个网页分别也是对各自的表进行添加,显示,更新以及删除记录的功能。

其实,这就是一个小程序,基本的功能都齐全。

-------------------------------------------------------------------------------------------------------------------------------------

根据此篇博文,我们来学习一下继承。
打开程序,我们会到四个网页的cs代码与四个类别98%相同,只是每个表的主键名,以及存储过程名称等不一样。继承是把相同而共用的属性,方法,函数放置于父类中,这样继承的类,就是使用到这些共用的protected或public的程序块。尽可能简化,变化的地方尽量未端化去维护。

我们创建一个父类,比如叫BaseUnitCode.cs吧。

首先我们对比四个类别中,属性部分,只有

复制代码

 private string _Unit1;      public string Unit1 {      get { return _Unit1; }      set { _Unit1 = value; }}

复制代码


不相同,因此我们就把它留在原本的类别中。其余的属性都移至父类BaseUnitCode,还有一句,就是逻辑处理的类实例

BusinessBase objBusinessBase = new BusinessBase();


在每个类别中也一样,因此也移至父类,下面是刚才重构好的父类。



接下来,我看到每个类别的GetAll(), Insert(), Update(), Delete()方法中,只有一些参数名,参数值,以及存储过程名有差异。下面是每个方法移至父类之后,作相应的修改:

GetAll()方法:


Comment out的代码,就是移到父类的代码,需要修改方法以及修饰符为Protected,这因为只是想让继承这个父类的类访问到即可。而刚才上面属性,还是保持原样“public”。
由于存储程名称在每个类别都不一样,因此方法名改为带一个参数的方法。


Insert()方法:


重构之后,Insert()方法被改为带三个参数的方法,这样解决传入主键,主键值,以及Insert的存储过程不一样的问题。

同样,Update():



Delete()方法重构:

 
Ok,我们的父类重构好了:

BaseUnitCode.cs

using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Web;/// <summary>/// Summary description for BaseUnitCode/// </summary>namespace Insus.NET{    public class BaseUnitCode    {        private string _Description;        private string _CreateBy;        private string _UpdateBy;        public string Description        {            get { return _Description; }            set { _Description = value; }        }        public string CreateBy        {            get { return _CreateBy; }            set { _CreateBy = value; }        }        public string UpdateBy        {            get { return _UpdateBy; }            set { _UpdateBy = value; }        }        BusinessBase objBusinessBase = new BusinessBase();        public BaseUnitCode()        {            //            // TODO: Add constructor logic here            //        }             protected DataTable GetAll(string procedureName)        {            return objBusinessBase.GetDataToDataSet(procedureName).Tables[0];        }        protected void Insert(string paramName, string paramValue, string procedurename)        {            Parameter[] parameter = {                                       new Parameter (paramName,SqlDbType.NVarChar,-1,paramValue),                                       new Parameter ("@Description",SqlDbType.NVarChar,-1,_Description),                                       new Parameter ("@CreateBy",SqlDbType.NVarChar,-1,_CreateBy)                                                                        };            objBusinessBase.ExecuteProcedure(procedurename, parameter);        }        protected void Update(string paramName, string paramValue, string procedurename)        {            Parameter[] parameter = {                                       new Parameter (paramName,SqlDbType.NVarChar,-1,paramValue),                                       new Parameter ("@Description",SqlDbType.NVarChar,-1,_Description),                                       new Parameter ("@UpdateBy",SqlDbType.NVarChar,-1,_UpdateBy)                                    };            objBusinessBase.ExecuteProcedure(procedurename, parameter);        }               protected void Delete(string paramName, string paramValue, string procedurename)        {            Parameter[] parameter = {                                       new Parameter (paramName,SqlDbType.NVarChar,-1,paramValue)                                    };            objBusinessBase.ExecuteProcedure(procedurename, parameter);        }    }}


接下来,我们需要在每一个UnitCode1.cs至UnitCode4.cs分别继承这个父类,下面只演法UnitCode1.cs,其余的UnitCode2至UnitCode4参考就是了。

 

 下面是重构好的类别:

UnitCode1.cs

using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Web;/// <summary>/// Summary description for UnitCode1/// </summary>namespace Insus.NET{    public class UnitCode1 : BaseUnitCode    {        private string _Unit1;        public string Unit1        {            get { return _Unit1; }            set { _Unit1 = value; }        }        public UnitCode1()        {            //            // TODO: Add constructor logic here            //        }        public DataTable GetAll()        {            return GetAll("usp_UnitCode1_GetAll");        }        public void Insert()        {            Insert("@Unit1", _Unit1, "usp_UnitCode1_Insert");        }        public void Update()        {            Update("@Unit1", _Unit1, "usp_UnitCode1_Update");        }        public void Delete()        {            Delete("@Unit1", _Unit1, "usp_UnitCode1_Delete");        }    }}

 

UnitCode2.cs

using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Web;/// <summary>/// Summary description for UnitCode1/// </summary>namespace Insus.NET{    public class UnitCode2 : BaseUnitCode    {        private string _Unit2;        public string Unit2        {            get { return _Unit2; }            set { _Unit2 = value; }        }                public UnitCode2()        {            //            // TODO: Add constructor logic here            //        }        public DataTable GetAll()        {            return GetAll("usp_UnitCode2_GetAll");        }        public void Insert()        {            Insert("@Unit2", _Unit2, "usp_UnitCode2_Insert");        }        public void Update()        {            Update("@Unit2", _Unit2, "usp_UnitCode2_Update");        }        public void Delete()        {            Delete("@Unit2", _Unit2, "usp_UnitCode2_Delete");        }    }}

 

UnitCode3.cs

using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Web;/// <summary>/// Summary description for UnitCode3/// </summary>namespace Insus.NET{    public class UnitCode3 : BaseUnitCode    {        private string _Unit3;        public string Unit3        {            get { return _Unit3; }            set { _Unit3 = value; }        }               public UnitCode3()        {            //            // TODO: Add constructor logic here            //        }        public DataTable GetAll()        {            return GetAll("usp_UnitCode3_GetAll");        }        public void Insert()        {            Insert("@Unit3", _Unit3, "usp_UnitCode3_Insert");        }        public void Update()        {            Update("@Unit3", _Unit3, "usp_UnitCode3_Update");        }        public void Delete()        {            Delete("@Unit3", _Unit3, "usp_UnitCode3_Delete");        }    }}

 

UnitCode4.cs

using System;using System.Collections.Generic;using System.Data;using System.Linq;using System.Web;/// <summary>/// Summary description for UnitCode1/// </summary>namespace Insus.NET{    public class UnitCode4 : BaseUnitCode    {        private string _Unit4;        public string Unit4        {            get { return _Unit4; }            set { _Unit4 = value; }        }               public UnitCode4()        {            //            // TODO: Add constructor logic here            //        }        public DataTable GetAll()        {            return GetAll("usp_UnitCode4_GetAll");        }        public void Insert()        {            Insert("@Unit4", _Unit4, "usp_UnitCode4_Insert");        }        public void Update()        {            Update("@Unit4", _Unit4, "usp_UnitCode4_Update");        }        public void Delete()        {            Delete("@Unit4", _Unit4, "usp_UnitCode4_Delete");        }    }}

 
类别重构完成,接下来,我们对UnitCode1.aspx.cs至UnitCode4.aspx.cs进行重构。因为这四个页面的类,也有很多相同的代码。重构之前,先创建一个页面的基类,暂叫它为BasePage,此类别继承了

 
每个.aspx.cs继承刚才写的BasePage类,把InsusJsUtility objInsusJsUtility = new InsusJsUtility(); 这句拿掉,并移至BasePage中,根据继承的精神,它足够条件移了。



移至BasePage之后,需要添加修饰符protected,这样每个.aspx.cs才可以访问得到。

BasePage.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;/// <summary>/// Summary description for BasePage/// </summary>namespace Insus.NET{    public class BasePage : System.Web.UI.Page    {        protected InsusJsUtility objInsusJsUtility = new InsusJsUtility();    }}

 
发现每个.aspx.cs代码,有两句重复了,需要删除。

 
接下来,我们眼睛注意到每个.aspx.cs的Data_Binding()方法中,均有此一句:

((ISetValable)this.Master).SetValue("单位码X");


因此Insus.NET把它封装入BasePage类中:

 
然后在每个.aspx.cs中,拿掉((ISetValable)this.Master).SetValue("单位码X"); 这句,并改为如下图高亮语句。



到此为止,Insus.NET暂停对.cs代码重构,转而看到Html代码。如下图中的插入记录代码,在四处个网页中每个.aspx都是相同的,因此Insus.NET对这些重构。

 

对这部分的重构,只有创建用户控件(ascx),然后搬移过去,完成之后,再把这个用户控件拉至网页.aspx中:

InsertForm.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="InsertForm.ascx.cs" Inherits="Sys_InsertForm" %><table class="table">    <tr class="tableRow">        <td class="tableCell" style="width: 35%;">单位码</td>        <td class="tableCell">说明</td>        <td style="width: 12%; text-align: center;" class="tableCell">操作</td>    </tr>    <tr>        <td class="tableCell">            <asp:TextBox ID="TextBoxUnitCode" runat="server" CssClass="textbox" BackColor="#ffff6f"></asp:TextBox>            <asp:RequiredFieldValidator ID="RequiredFieldValidator2" runat="server" ControlToValidate="TextBoxUnitCode"                Display="none" ErrorMessage="单位码必须填写。" ValidationGroup="GeneralInsert"></asp:RequiredFieldValidator>        </td>        <td class="tableCell">            <asp:TextBox ID="TextBoxDescription" runat="server" CssClass="textbox"></asp:TextBox>        </td>        <td style="width: 12%;" class="tableCell">            <asp:ValidationSummary ID="ValidationSummary1" runat="server" EnableClientScript="true"                ShowMessageBox="true" ShowSummary="false" ValidationGroup="GeneralInsert" />            <asp:Button ID="ButtonCreate" runat="server" OnClick="ButtonCreate_Click" Text="创建"                ValidationGroup="GeneralInsert" />        </td>    </tr></table>


由于每个.aspx创建事件不一样,为了保持原有在.aspx.cs的事件,Insus.NET决定在用户控件中再public Click 事件。


上图中,还写两个属性,分别是两个文本框的属性,这是为了让.aspx还能与用户控件的两个文本框的交互。

 用户控件重构好之后,当然需要拉至网页中去,有一个地方是需要注意的,在用户控件,还要写上OnClick事件,OnClick="ButtonCreate_Click":

 
在.aspx.cs代码页中,一些代码需要异动,参考下图高亮位置:


 改程序,就得一步一个脚印,现在我们把目光放在每个.aspx的GridView控件上,它是显示记录,编辑记录以及删除等功能集成。有很高的相似度。只是Gridview的ID,DataKeyNames,以及OnRowEditing,OnRowCancelingEdit,OnRowUpdating,OnRowDeleting事件名称不一样,最后是绑定主键时,也不一样:

<ItemTemplate>     <%# Eval("UnitX") %></ItemTemplate>


这部分重构,相似度,但好象又很具有独立性,无法分开。现在Insus.NET决定对这些ID以及事件名改为一样。删除箭头所指的数字:

改完之后,如下代码一样,Insus.NET只列了个网页,如Unitcode4(部分):

复制代码

<asp:GridView ID="GridViewUnitCode" runat="server" DataKeyNames="Unit4" AutoGenerateColumns="false" ShowHeader="false" CellPadding="2" CellSpacing="0" Width="100%" BorderWidth="1px" BorderColor="#c0c0c0" BorderStyle="solid"                HeaderStyle-Height="25" RowStyle-Height="25" HeaderStyle-BackColor="#efebde" OnRowEditing="GridViewUnitCode_RowEditing"                OnRowCancelingEdit="GridViewUnitCode_RowCancelingEdit" OnRowUpdating="GridViewUnitCode_RowUpdating"                OnRowDeleting="GridViewUnitCode_RowDeleting">                <Columns>                    <asp:TemplateField>                        <ItemStyle BorderStyle="solid" BorderWidth="1px" BorderColor="#c0c0c0" Width="35%" />                        <ItemTemplate>                            <%# Eval("Unit4") %>                        </ItemTemplate>                    </asp:TemplateField>

复制代码


当然在每个UnitCode1~3.aspx.cs的事件中,也应该修改,参考下图,把箭头的数据全删除。


重名命重构,往往改动的地方都较多。全部改完之后,所有UnitCode1~4.aspx只差下图高亮位置的差异了:



怎样解决这些差异,它是一个表字段,而且是主键。动态产生或是加载是否可行,想到了,行动就是了。在GridView中,去掉DataKeyNames="Unit1"属性。在显示ItemTemple中,改为一个标签,并为GridView添加一个事件 OnRowDataBound="GridViewUnitCode_RowDataBound"。



在.aspx.cs中,添加一个变量,四个网页的变量值不同,分别为
string _DataKeyName = "Unit1";
string _DataKeyName = "Unit2";
string _DataKeyName = "Unit3";
string _DataKeyName = "Unit4";

参考下面动画:

 
程序经此一改,每个页面的html又一样了。所以我们可以把其中一页的GridView html代码块搬移至一个用户控件之内。创建一个用户控件:

OperationForm.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="OperationForm.ascx.cs" Inherits="Sys_OperationForm" %><asp:GridView ID="GridViewUnitCode" runat="server" AutoGenerateColumns="false" ShowHeader="false" CellPadding="2" CellSpacing="0" Width="100%" BorderWidth="1px" BorderColor="#c0c0c0" BorderStyle="solid"    HeaderStyle-Height="25" RowStyle-Height="25" HeaderStyle-BackColor="#efebde" OnRowEditing="GridViewUnitCode_RowEditing"    OnRowCancelingEdit="GridViewUnitCode_RowCancelingEdit" OnRowUpdating="GridViewUnitCode_RowUpdating"    OnRowDeleting="GridViewUnitCode_RowDeleting" OnRowDataBound="GridViewUnitCode_RowDataBound">    <Columns>        <asp:TemplateField>            <ItemStyle BorderStyle="solid" BorderWidth="1px" BorderColor="#c0c0c0" Width="35%" />            <ItemTemplate>                <asp:Label ID="LabelUnitCode" runat="server" Text=""></asp:Label>            </ItemTemplate>        </asp:TemplateField>        <asp:TemplateField>            <ItemStyle BorderStyle="solid" BorderWidth="1px" BorderColor="#c0c0c0" />            <ItemTemplate>                <%# Eval("Description") %>            </ItemTemplate>            <EditItemTemplate>                <asp:TextBox ID="TextBoxDescription" runat="server" Text='<%# Eval("Description") %>' CssClass="textbox"></asp:TextBox>            </EditItemTemplate>        </asp:TemplateField>        <asp:TemplateField>            <ItemStyle BorderStyle="solid" BorderWidth="1px" BorderColor="#c0c0c0" Width="8%" />            <ItemTemplate>                <asp:Button ID="ButtonEdit" runat="server" Text="编辑" CommandName="Edit" CausesValidation="false" />            </ItemTemplate>            <EditItemTemplate>                <asp:ValidationSummary ID="ValidationSummary2" runat="server" EnableClientScript="true"                    ShowMessageBox="true" ShowSummary="false" ValidationGroup="GrieviewUpdate" />                <asp:Button ID="ButtonUpdate" runat="server" Text="更新" CommandName="Update" ValidationGroup="GrieviewUpdate" />                <asp:Button ID="ButtonCancel" runat="server" Text="取消" CommandName="Cancel" CausesValidation="false" />            </EditItemTemplate>        </asp:TemplateField>        <asp:TemplateField HeaderText="删除">            <ItemStyle BorderStyle="solid" BorderWidth="1px" BorderColor="#c0c0c0" Width="4%" />            <ItemTemplate>                <asp:Button ID="ButtonDelete" runat="server" Text="删除" CommandName="Delete" CausesValidation="false" />                <ajaxToolkit:ConfirmButtonExtender ID="ConfirmButtonExtender1" runat="server" TargetControlID="ButtonDelete"                    ConfirmText="确认删除记录?">                </ajaxToolkit:ConfirmButtonExtender>            </ItemTemplate>        </asp:TemplateField>    </Columns></asp:GridView>


在OperationForm.ascx.cs中,需要处理几个问题,一是GridView的事件,主键,还是数据绑定的问题等。现在Insus.NET先解决GridView事件:
宣告几个事件,除了GridViewUnitCode_RowDataBound(object sender, GridViewRowEventArgs e)无需处理,因为它与页没有任何交互,只是为GridView显示数据而已。

 

Ok, 我们把用户控件拉至网页,并写好事件:

下面是我们要解决主键,数据绑定,还有在GrieView显示主键的问题,在用户控件中,写一个只写属性,因为只需要为用户控件写入属性,不必为从用户控件获取值。

 private string _DataKeyName;    public string DataKeyName    {        set { _DataKeyName = value; }    }


接下来,我们又需要去到每一个.aspx.cs中,为刚才的写好的属性赋值,你将看到下图高亮代码行,这样子,在每个网页运行时,就把网页的主键字符名称传至用户控件内。

 
处理Gridview显示主键时,把下面的方法全搬至用户控件中,其余网页相同的事件删除。

复制代码

 protected void GridViewUnitCode_RowDataBound(object sender, GridViewRowEventArgs e)    {        if (e.Row.RowType != DataControlRowType.DataRow) return;        var drv = e.Row.DataItem as DataRowView;        if (e.Row.FindControl("LabelUnitCode") != null)        {            var lbl = e.Row.FindControl("LabelUnitCode") as Label;            lbl.Text = drv[_DataKeyName].ToString();        }    }

复制代码


为了让.aspx.cs能与用户控件更好的交互,需要在站点创建一个接口:

IGridViewControlable.cs

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI.WebControls;/// <summary>/// Summary description for IGridViewControlable/// </summary>namespace Insus.NET{    public interface IGridViewControlable    {        GridView GetGridViewControl();    }}


在用户控件OperationForm.ascx.cs实作它。


在每一个.aspx.cs代码页中,写一个get属性:

View Code

GridView GridViewUnitCode    {        get        {            return ((IGridViewControlable)this.OperationForm1).GetGridViewControl();        }    }

 
写到此,还没有完毕,精彩还在后头。我们再写一个基类,此基将为前面写好的两个用户控件继承。写用户控件的基类,跟页面的基类完全一样。看到否,这基类是继承了System.Web.UI.UserControl:


基类写好,去分别打开以前写好的两个用户控件,继承这个用户控件的基类:

 


然后把在InsertForm.ascx.cs中下面代码移至BaseUserControl.cs控件中:

复制代码

 public event EventHandler Click;    protected void ButtonCreate_Click(object sender, EventArgs e)    {        if (Click != null)        {            Click(this, e);        }    }

复制代码


相同的情况,把OperationForm.cs中下面代码也移至BaseUserControl.cs控件中,移至之后,需要在这个基类的用户控件中,引用命名空间 using System.Web.UI.WebControls;

View Code

 public event GridViewEditEventHandler RowEditing;    public event GridViewCancelEditEventHandler RowCancelingEdit;    public event GridViewUpdateEventHandler RowUpdating;    public event GridViewDeleteEventHandler RowDeleting;    protected void GridViewUnitCode_RowEditing(object sender, GridViewEditEventArgs e)    {        if (RowEditing != null)            RowEditing(sender, e);    }    protected void GridViewUnitCode_RowCancelingEdit(object sender, GridViewCancelEditEventArgs e)    {        if (RowCancelingEdit != null)            RowCancelingEdit(sender, e);    }    protected void GridViewUnitCode_RowUpdating(object sender, GridViewUpdateEventArgs e)    {        if (RowUpdating != null)            RowUpdating(sender, e);    }    protected void GridViewUnitCode_RowDeleting(object sender, GridViewDeleteEventArgs e)    {        if (RowDeleting != null)            RowDeleting(sender, e);    }


也就是说,当多用户控件中共用的属性,方法或是函数,也可以写在基类中。
接下来,我们还看到每个.aspx.cs还在一段相同的代码:

复制代码

GridView GridViewUnitCode    {        get        {            return ((IGridViewControlable)this.OperationForm1).GetGridViewControl();        }    }

复制代码


Insus.NET也想把它移至基类BasePage.cs中去,直接cut and paste,它会提示找不到this.OperationForm1这个物件。不管怎样,出错就出错,移过去再说,其余的删除。解决问题,还是使用接口吧:

IUserControlable

using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Web.UI;/// <summary>/// Summary description for IUserControlable/// </summary>namespace Insus.NET{    public interface IUserControlable    {        UserControl GetUserControl();    }}


然后每个UnitCode1~4.aspx.cs均实作这个接口,下仅在一个类演示:

 

我们打开BasePage基类,看下动画,很简单把刚才找不到物件的问题解决了:



ok,此博文到此为止,望看过的网友,能从中学习或温习到继承知识,了解到类别与父类,网页与基类页,用户控件与用户控件基类,还有的是网页与用户控件之间的交互通讯等。
最终重构好的程序,可以下载与博文开头的原程序对比。
http://download.cnblogs.com/insus/ASPDOTNET/Ref_Org_inhert.rar

 

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消