转至繁体中文版     | 网站首页 | 图文教程 | 资源下载 | 站长博客 | 图片素材 | 武汉seo | 武汉网站优化 | 
最新公告:     敏韬网|教学资源学习资料永久免费分享站!  [mintao  2008年9月2日]        
您现在的位置: 学习笔记 >> 图文教程 >> 站长学院 >> Web开发 >> 正文
使用反射将业务对象绑定到 ASP.NET 窗体控件         ★★★★

使用反射将业务对象绑定到 ASP.NET 窗体控件

作者:闵涛 文章来源:闵涛的学习笔记 点击数:1516 更新时间:2009/4/23 10:40:58

使用反射将业务对象绑定到 ASP.NET 窗体控件

发布日期: 12/10/2004 | 更新日期: 12/10/2004

John Dyer
Dallas Theological Seminary

适用于:
Microsoft Visual Studio 2005 及早期版本
ASP.NET 1.1
C# 编程语言
Visual Basic 编程语言

摘要:使用反射以单行代码将业务对象绑定到 ASP.NET Web 窗体,从而降低复杂性并减少错误。(本文包含一些指向英文站点的链接。请注意,在示例文件中,程序员的注释使用的是英文,本文中将其译为中文是为了便于读者理解。)

下载 MSDFormBinding.msi 示例文件。

*
本页内容
引言引言简化和缩短窗体代码简化和缩短窗体代码开始:从反射中检索属性列表开始:从反射中检索属性列表将对象属性值绑定到控件将对象属性值绑定到控件用已知属性设置未知控件的值用已知属性设置未知控件的值反转过程:BindControlsToObject反转过程:BindControlsToObject性能和 FormBinding 方案的扩展性能和 FormBinding 方案的扩展结论结论参考资料参考资料

引言

在 Web 开发人员的最常见任务之中,有一项任务是他们要反复执行的:建立更新数据库表的简单窗体。我们将创建一个列表页面和一个窗体页面,列表页面中以表格形式显示记录,窗体页面中带有用于各个数据库字段的适当的窗体控件。许多开发人员还使用表示数据库表的业务对象将代码组织到分为多层的设计中。如果以业务对象 (Document) 来表示数据库表 (Documents),许多窗体的代码看上去将如下所示:

<script runat="server">
protected void Page_Load(Object Src, EventArgs E) {
if (!IsPostBack) {
   Document document = 
        Documents.GetDocument(Request.QueryString["DocumentID"]);

   Title.Text = document.Title;
   Active.Checked = document.Active;
   CreatedDate.Text = document.CreatedDate.ToString();
   AuthorID.FindByValue(document.AuthorID.ToString()).Selected = 
        true;
   // ... 等等
   HtmlBody.Text = document.HtmlBody;
}
}
protected void SaveButton_Click(Object Src, EventArgs E) {
   Document document = 
        Documents.GetDocument(Request.QueryString["DocumentID"]);

   document.Title = Title.Text;
   document.Active = Active.Checked;
   document.CreatedDate = Convert.ToDateTime(CreatedDate.Text);
   document.AuthorID = Convert.ToInt32(AuthorID.SelectedItem.Value);
   // ... 等等
   document.HtmlBody = HtmlBody.Text;

   Documents.Update(document);
}
</script>
返回页首返回页首

简化和缩短窗体代码

在以上代码中,对每个控件进行显式转换,并将其设置为窗体控件的正确属性。根据属性和窗体控件的数量,这部分代码可能会变长并难以管理。代码还应包含类型转换的错误更正和 ListControl,这将进一步增加复杂性。即使窗体是由代码生成工具(例如 Eric J. Smith 的优秀的 CodeSmith)生成的,当需要任何自定义逻辑关系时,很容易引入错误。

使用反射,可以仅使用单行代码便将业务对象的所有属性绑定到相应的窗体控件,从而减少代码的行数并增强可读性。完成反射系统的建立后,以上代码将简化为:

protected void Page_Load(Object Src, EventArgs E) {
   if (!IsPostBack) {
      Document document = 
     Documents.GetDocument(Request.QueryString["DocumentID"]);

      FormBinding.BindObjectToControls(document);
   }
}
protected void Save_Click(Object Src, EventArgs E) {
   Document document = 
        Documents.GetDocument(Request.QueryString["DocumentID"]);

   FormBinding.BindControlsToObject(document);

   Documents.Update(document);
}

此代码可用于所有标准的 ASP.NET 控件(TextBoxDropDownListCheckBox 等)和许多第三方控件(例如 Free TextBox 和 Calendar Popup)。无论有多少业务对象属性和窗体控件,这一行代码都能提供所需的全部功能,只要窗体控件的 ID 与业务对象属性名相匹配。

返回页首返回页首

开始:从反射中检索属性列表

首先,我们需要检查业务对象的属性,并查找与业务对象属性名具有相同 ID 的 ASP.NET 控件。以下代码构成了绑定查找的基础:

public class FormBinding {
   public static void BindObjectToControls(object obj, 
        Control container) {
      if (obj == null) return;
      Type objType = obj.GetType();
      PropertyInfo[] objPropertiesArray = 
              objType.GetProperties();

      foreach (PropertyInfo objProperty in objPropertiesArray) {

         Control control = 
                     container.FindControl(objProperty.Name);
         if (control != null) {
             // 处理控件 ...
         }
      }
   }
}

在以上代码中,方法 BindObjectsToControls 接受了业务对象 obj 和一个容器控件。容器控件通常是当前 Web 窗体的 Page 对象。如果所用版本是会在运行时更改控件嵌套顺序的 ASP.NET 1.x MasterPages,您将需要指定窗体控件所在的 Content 控件。这是在 ASP.NET 1.x 中,FindControl 方法对嵌套控件和命名容器的处理方式导致的。

在以上代码中,我们获取了业务对象的 Type,然后使用该 Type 来获取 PropertyInfo 对象的数组。每个 PropertyInfo 对象都包含关于业务对象属性以及从业务对象获取和设置值的能力的信息。我们使用 foreach 循环检查具有与业务对象属性名 (PropertyInfo.Name) 对应的 ID 属性的 ASP.NET 控件的容器。如果找到控件,则尝试将属性值绑定到该控件。

返回页首返回页首

将对象属性值绑定到控件

过程中的大部分操作是在此阶段执行的。我们需要用对象的属性值来填充找到的控件。一种实现方法是为每种控件类型创建一个 if ... else 语句。派生自 ListControlDropDownListRadioButtonListCheckBoxListListBox)的所有控件都具有可以统一访问的公用接口,所以可以将它们编组在一起。如果找到的控件是 ListControl,我们可以将其作为 ListControl 进行转换,然后设置选定项:

Control control = container.FindControl(objProperty.Name);
if (control != null) {
   if (control is ListControl) {
      ListControl listControl = (ListControl) control;
      string propertyValue = objProperty.GetValue(obj, 
              null).ToString();
      ListItem listItem = 
             listControl.Items.FindByValue(propertyValue);
      if (listItem != null) listItem.Selected = true;
   } else {
      // 处理其他控件类型
   }
}

不幸的是,其他控件类型并不从父类中派生。以下几个公用控件都具有 .Text 字符串属性:TextBoxLiteralLabel。但该属性不是从公用父类中派生出来的,所以需要分别转换每种控件类型。我们还需要转换其他控件类型,例如 Calendar 控件,以便使用适当的属性(在 Calendar 的例子中,是 SelectedDate 属性)。要包含所有标准的 ASP.NET 窗体控件,并访问窗体控件的正确属性并不需要太多的代码行。

if (control is ListControl) {
   ListControl listControl = (ListControl) control;
   string propertyValue = objProperty.GetValue(obj, 
        null).ToString();
   ListItem listItem = listControl.Items.FindByValue(propertyValue);
   if (listItem != null) listItem.Selected = true;
} else if (control is CheckBox) {
   if (objProperty.PropertyType == typeof(bool))
      ((CheckBox) control).Checked = (bool) 
              objProperty.GetValue(obj, null);
} else if (control is Calendar) {
   if (objProperty.PropertyType == typeof(DateTime))
      ((Calendar) control).SelectedDate = (DateTime) 
               objProperty.GetValue(obj, null);
} else if (control is TextBox) {
   ((TextBox) control).Text = objProperty.GetValue(obj, 
        null).ToString();
} else if (control is Literal)(
   //... 等等。还可用于标签等属性。
}

此方法完整地涵盖了标准的 ASP.NET 1.x 控件。从这个角度来看,我们拥有了功能齐全的 BindObjectToControls 方法。但在起作用的同时,此方法的应用范围会受到限制,因为它仅考虑内置的 ASP.NET 1.x 控件。如果要支持新的 ASP.NET 2.0 控件,或者要使用任何第三方控件,我们必须在 FormBinding 项目中引用控件的程序集,并将控件类型添加到 if ... else 列表。

此问题的解决方案是第二次使用反射,以查看各个控件的属性,并找出控件是否具有与业务对象的属性类型对应的属性类型。

返回页首返回页首

用已知属性设置未知控件的值

如上所述,有些控件共享字符串属性 .Text,大多数窗体控件以实质相同的方式使用此属性。该属性用于获取和设置用户输入的数据。有大量控件还使用了其他一些公用属性和属性类型。以下是这些属性中的一些:称为 .SelectedDateDateTime 属性,它在许多日历和日期选取器控件中使用;称为 .Checked 的布尔属性,它在布尔型控件中使用;称为 .Value 的字符串属性,它常见于隐藏控件。这四个属性(string Textstring Valuebool CheckedDateTime SelectedDate)是最常见的控件属性。如果可以将系统设计成无论何种控件类型,都绑定到这些属性,那么我们的绑定方法将适用于使用那四个属性的任何控件。

在以下代码中,我们将第二次使用反射(这一次是对窗体控件使用,而不是对业务对象使用),以确定它是否具有任何常用属性。如果有,则尝试将业务对象的属性值设置为控件的属性。作为示例,我们将对整个 PropertyInfo 数组进行迭代,并查找称为 .Text 的字符串属性。如果控件具有该属性,则将数据从业务对象发送到该控件的属性。

if (control is ListControl) {
   // ...
} else {
   // 获取控件的类型和属性
   //
   Type controlType = control.GetType();
   PropertyInfo[] controlPropertiesArray = 
        controlType.GetProperties();

   // 查找 .Text 属性
   //
   foreach (PropertyInfo controlProperty 
        in controlPropertiesArray) {
      if (controlPropertiesArray.Name == "Text" && 
              controlPropertiesArray.PropertyType == typeof(String)) {
         // 设置控件的 .Text 属性
         //
         controlProperty.SetValue(control, 
                   (String) objProperty.GetValue(obj, null), null);

      }
   }

}

如果找到 .Text,则使用 PropertyInfo 类的 GetValue 方法从业务对象的属性中检索值。然后,使用控件的 .Text 属性的 SetValue 方法。在此,我们还使用 Type 命令将控件的属性设置为 typeof(String),并使用 (String) 符号显式转换来自属性的值。

为了使 BindObjectToControls 方法完整,我们还需要处理其他公用属性,即 .Checked.SelectedDate.Value。在以下代码中,我们将控件属性搜索打包到称为 FindAndSetControlProperty 的辅助方法中,以简化代码。

if (control is ListControl) {
   // ...
} else {
   // 获取控件的属性
   //
   Type controlType = control.GetType();
   PropertyInfo[] controlPropertiesArray = 
        controlType.GetProperties();

   bool success = false;
   success = FindAndSetControlProperty(obj, 
        objProperty, control, contro

[1] [2]  下一页


[C语言系列]NET 中C#的switch语句的语法  [系统软件]托拽Explore中的文件到VB.net的窗口
[系统软件]Boost库在XP+Visual C++.net中的安装  [常用软件]新配色面板:Paint.Net3.0RC1官方下载
[常用软件]用内建的“Net Meeting”聊天  [VB.NET程序]Henry的VB.NET之旅(三)—共享成员
[VB.NET程序]Henry的VB.NET之旅(二)—构造与析构  [VB.NET程序]Henry的VB.NET之旅(一)—失踪的窗体
[VB.NET程序]在托盘上显示Balloon Tooltip(VB.NET)  [VB.NET程序]Henry手记-VB.NET中动态加载Treeview节点(二)
教程录入:mintao    责任编辑:mintao 
  • 上一篇教程:

  • 下一篇教程:
  • 【字体: 】【发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
      注:本站部分文章源于互联网,版权归原作者所有!如有侵权,请原作者与本站联系,本站将立即删除! 本站文章除特别注明外均可转载,但需注明出处! [MinTao学以致用网]
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)

    同类栏目
    · Web开发  · 网页制作
    · 平面设计  · 网站运营
    · 网站推广  · 搜索优化
    · 建站心得  · 站长故事
    · 互联动态
    更多内容
    热门推荐 更多内容
  • 没有教程
  • 赞助链接
    更多内容
    闵涛博文 更多关于武汉SEO的内容
    500 - 内部服务器错误。

    500 - 内部服务器错误。

    您查找的资源存在问题,因而无法显示。

    | 设为首页 |加入收藏 | 联系站长 | 友情链接 | 版权申明 | 广告服务
    MinTao学以致用网

    Copyright @ 2007-2012 敏韬网(敏而好学,文韬武略--MinTao.Net)(学习笔记) Inc All Rights Reserved.
    闵涛 投放广告、内容合作请Q我! E_mail:admin@mintao.net(欢迎提供学习资源)

    站长:MinTao ICP备案号:鄂ICP备11006601号-18

    闵涛站盟:医药大全-武穴网A打造BCD……
    咸宁网络警察报警平台