分享
 
 
 

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

王朝c#·作者佚名  2006-12-17
窄屏简体版  字體: |||超大  

使用反射将业务对象绑定到 ASP.NET 窗体控件发布日期: 12/10/2004更新日期: 12/10/2004John Dyer

Dallas Theological Seminary

适用于:

Microsoft Visual Studio 2005 及早期版本

ASP.NET 1.1

C# 编程语言

Visual Basic 编程语言

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

下载 MSDFormBinding.msi 示例文件。

本页内容

Document) 来表示数据库表 (Documents),许多窗体的代码看上去将如下所示:

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

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

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

返回页首开始:从反射中检索属性列表首先,我们需要检查业务对象的属性,并查找与业务对象属性名具有相同 ID 的 ASP.NET 控件。以下代码构成了绑定查找的基础:

在以上代码中,方法 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 语句。派生自 ListControl(DropDownList、RadioButtonList、CheckBoxList 和 ListBox)的所有控件都具有可以统一访问的公用接口,所以可以将它们编组在一起。如果找到的控件是 ListControl,我们可以将其作为 ListControl 进行转换,然后设置选定项:

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

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

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

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

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

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

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

以上属性检查的顺序很重要,因为有些控件具有以上属性中的多个,但我们只想设置一个。例如,CheckBox 控件既有 .Text 属性也有 .Checked 属性。在此示例中,我们希望使用 .Checked 属性而不是 .Text 属性,所以将 .Checked 放在属性搜索顺序的首位。任何情况下,如果找到具有正确名称和类型的控件属性,则尝试将控件的属性设置为业务对象属性的值。

从这个角度来看,我们拥有了功能齐全的 BindObjectToControls 方法。利用该方法,我们可以在 ASPX 窗体上的任何地方,使用任何类和控件的任意组合进行调用,而这确实有效。现在,我们需要创建在提交窗体时进行反转的方法。我们需要从表示用户输入的控件中检索新值,而不是将控件属性的值设置为业务对象的值。

返回页首反转过程:BindControlsToObject在 BindControlsToObject 方法中,我们将以同样的方式开始,即从业务对象中检索属性的列表,然后使用 FindControl 方法找到具有与对象属性相匹配的 ID 的控件。如果找到控件,则检索值并将该值返回给业务对象。此部分还将包含 ListControl 的单独代码,因为这些控件具有公用接口。我们将使用另一种辅助方法来搜索并检索控件中的值,然后将该值返回给业务对象。

完成这两种方法后,我们的窗体语法将得到简化,如以上简化和缩短窗体代码中所述。每个属性和控件的类型转换与错误更正都是自动进行的。这两种方法(BindObjectToControls 和 BindControlsToObject)为开发人员创建窗体提供了很大的灵活性。它们还可以用于处理以下这些常见方案:

FormBinding 方法将处理剩下的一切。

TextBox 更改为第三方的 HTML 编辑器控件,他/她仅需要确保新控件具有以上属性之一(例如 .Text ),窗体将以与之前完全一致的方式进行工作。

TextBox 控件也可以快速生成窗体,但输入仍将转换为适用于业务对象属性的正确类型。例如,可以用 TextBox 控件来代替 Calendar 控件或第三方的日期选取器控件。只要用户输入 DateTime 字符串作为值,便会将 TextBox 的 .Text 属性中的值转换为 DateTime,就如同它是日历控件上的 SelectedDate 属性一样。如果以后将 TextBox 更改为日期选取器控件,逻辑关系将保持不变。

Literal 控件,开发人员还可以快速创建“视图”页面。Literal 的 .Text 属性将被设置为业务对象属性的值,就如同它是 TextBox 一样。

BindObjectToControls 和 BindControlsToObject 的调用之后。

返回页首性能和 FormBinding 方案的扩展有些开发人员可能想知道,使用反射引起的性能下降是否值得。在我的测试中,使用了具有七种属性(int DocumentID、bool Active、DateTime Created、int CategoryID、String Title、string Author 和 String htmlText)的对象,BindObjectToControls 用时约 1/3 毫秒,BindControlsToObject 用时大约 1 毫秒。这些值是通过循环运行 1000 次 BindObjectToControls 和 BindControlsToObject 方法得到的。对于常见的“添加”和“编辑”窗体方案,这样的性能应不会引起任何重大的问题,而且确实能够提高开发速度和灵活性。

尽管此方法几乎适用于每种窗体,但有时可能需要修改以上代码。在某些方案中,开发人员要使用的控件可能并不使用以上属性之一作为其主要接口。在此情形中,需要更新 FormBinding 方法,以包括该属性和类型。

返回页首结论这两种 FormBinding 方法(BindObjectToControls 和 BindControlsToObject)可用于极大地简化窗体代码,并为 ASP.NET 窗体的开发提供了最大的灵活性。对它们的使用使我获益良多,希望您的团队同样能够从中受益。

返回页首参考资料•

作者简介

John Dyer 是 Dallas Theological Seminary 的顶级 Web 开发人员,负责指导他们富有盛誉的联机培训计划,该计划建立在 Telligent System 的 Community Server 之上。他还是广泛使用的 ASP.NET HTML 编辑器 FreeTextBox 的作者,该控件为除他之外的很多人带来了经济收益。在业余时间,他在 Dallas 神学院攻读神学硕士,并在准备 2005 年 1 月 1 日的婚礼。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有