.net中的反射(序章)

上传人:ji****n 文档编号:45155374 上传时间:2018-06-15 格式:DOCX 页数:17 大小:39.69KB
返回 下载 相关 举报
.net中的反射(序章)_第1页
第1页 / 共17页
.net中的反射(序章)_第2页
第2页 / 共17页
.net中的反射(序章)_第3页
第3页 / 共17页
.net中的反射(序章)_第4页
第4页 / 共17页
.net中的反射(序章)_第5页
第5页 / 共17页
点击查看更多>>
资源描述

《.net中的反射(序章)》由会员分享,可在线阅读,更多相关《.net中的反射(序章)(17页珍藏版)》请在金锄头文库上搜索。

1、引言引言反射是.Net 提供给我们的一件强力武器,尽管大多数情况下我们不常用到反射,尽管我们可能也不需要精通它,但对反射的使用作以初步了解在日后的开发中或许会有所帮助。反射是一个庞大的话题,牵扯到的知识点也很多,包括程序集、自定义特性、泛型等,想要完全掌握它非常不易。本文仅仅对反射做一个概要介绍,关于它更精深的内容,需要在实践中逐渐掌握。本文将分为下面几个部分介绍.Net 中的反射:1. 序章,我将通过一个例子来引出反射,获得对反射的第一印象。 2. 反射初步、Type 类、反射普通类型。(修改中,近期发布.) 3. 反射特性(Attribute)。 4. xxxx (待定) 5. . 序章序

2、章如果你还没有接触过反射,而我现在就下一堆定义告诉你什么是反射,相信你一定会有当头一棒的感觉。我一直认为那些公理式的定义和概念只有在你充分懂得的时候才能较好的发挥作用。所以,我们先来看一个开发中常遇到的问题,再看看如何利用反射来解决:在进行数据库设计的过程中,常常会建立一些基础信息表,比如说:全国的城市,又或者订单的状态。假设我们将城市的表,起名为 City,它通常包含类似这样的字段:Id Int Identity(1,1) 城市 IdName Varchar(50) 城市名称ZIP Varchar(10) 城市邮编. / 略这个表将供许多其他表引用。假如我们在建立一个酒店预订系统,那么酒店信

3、息表(Hotel)就会引用此表,用 CityId 字段来引用酒店所在城市。对于城市(City)表这种情况,表里存放的记录(城市信息)是不定的,意思就是说:我们可能随时会向这张表里添加新的城市(当某个城市的第一家酒店想要加入预订系统时,就需要在 City 表里新添这家酒店所在的城市)。此时,这样的设计是合理的。1.1.建表及其问题建表及其问题我们再看看另外一种情况,我们需要标识酒店预订的状态:未提交、已提交、已取消、受理中、已退回、已订妥、已过期。此时,很多开发人员会在数据库中建立一张小表,叫做 BookingStatus(预订状态),然后将如上状态加入进去,就好像这样:如同城市(City)表一

4、样,在系统的其他表,比如说酒店订单表(HotelOrder)中,通过字段 StatusId 引用这个表来获取酒店预订状态。然而,几个月以后,虽然看上去和城市表的用法一样,结果却发现这个表只在数据库做联合查询或者 只在程序中调用,却从来不做修改,因为预订流程确定下来后一般是不会变更的。在应用程序中,也不会给用户提供对这个表记录的增删改操作界面。而在程序中调用这个表时,经常是这种情况:我们需要根据预订状态对订单列表进行筛选。此时通常的做法是使用一个下拉菜单(DropDownList),菜单的数据源(DataSource),我们可以很轻易地通过一个 SqlDataReader 获得,我们将 Drop

5、DownList 的文本 Text 设为Status 字段,将值 Value 设为 Id 字段。此时,我们应该已经发现问题:1. 如果我们还有航班预订、游船预订,或者其他一些状态,我们需要在数据库中创建很多类似的小表,造成数据库表的数目过多。 2. 我们使用 DropDownList 等控件获取表内容时,需要连接到数据库进行查询,潜在地影响性能。 同时,我们也注意到三点:1. 此表一般会在数据库联合查询中使用到。假设我们有代表酒店订单的HotelOrder 表,它包含代表状态的 StatusId 字段,我们的查询可能会像这样:Select *, (Select Status From Book

6、ingStatus Where Id = HotelOrder.StatusId) as Status From HotelOrder。 2. 在应用程序中,此表经常作为 DropDownList 或者其他 List 控件的数据源。 3. 这个表几乎从不改动。 2.2.数组及其问题数组及其问题意识到这样设计存在问题,我们现在就想办法解决它。我们所想到的第一个办法是可以在程序中创建一个数组来表示预订状态,这样我们就可以删掉 BookingStatus 状态表(注意可以这样做是因为 BookingStatus 表的内容确定后几乎从不改动)。string BookingStatus = “NoUse

7、“, “未提交“,“已提交“,“已取消“,“受理中“,“已退回“,“已订妥“,“已过期“; / 注意数组的 0 号元素仅仅是起一个占位作用,以使程序简洁。因为StatusId 从 1 开始。我们先看它解决了什么:上面提到的问题 1、问题 2 都解决了,既不需要在数据库中创建表,又无需连接到数据库进行查询。我们再看看当我们想要用文本显示酒店的预订时,该怎么做(假设有订单类HotelOrder,其属性 StatusId 代表订单状态,为 int 类型 )。/ GetItem 用于获取一个酒店订单对象, orderId 为 int 类型,代表订单的 IdHotelOrder myOrder = Ge

8、tItem(orderId);lbStatus.Text = BookingStatusmyOrder.StatusId; /lbStatus是一个 Label 控件目前为止看上去还不错,现在我们需要进行一个操作,将订单的状态改为“受理中”。myOrder.StatusId = 4;很不幸,我们发现了使用数组可能带来的第一个问题:不方便使用,当我们需要更新不方便使用,当我们需要更新订单的状态值时,我们需要去查看订单的状态值时,我们需要去查看 BookingStatusBookingStatus 数组的定义数组的定义( (除非你记住所有状态的数字除非你记住所有状态的数字值值) ),然后根据状态值

9、在数组中的位置来给对象的属性赋值。,然后根据状态值在数组中的位置来给对象的属性赋值。我们再看另一个操作,如果某个订单的状态为“已过期”,就要对它进行删除:if(BookingStatusmyOrder.StatusId=“已过期“)DeleteItem(myOrder); / 删除订单此时的问题和上面的类似:我们需要手动输入字符串“已过期”,此时 Vs2005 的智能提示发挥不了任何作用,如果我们不幸将状态值记错,或者手误打错,就将导致程序错误,较为稳妥的做法还是按下 F12 导向到 BookingStatus 数组的定义,然后将“已过期”复制过来。现在,我们再看看如何来绑定到一个 DropD

10、ownList 下拉列表控件(Id 为 ddlStatus)上。ddlStatus.DataSource = BookingStatus;ddlStatus.DataBind();但是我们发现产生的 HTML 代码是这样:未提交已提交已取消受理中已退回已订妥已过期我们看到,列表项的 value 值与 text 值相同,这显然不是我们想要的,怎么办呢?我们可以给下拉列表写一个数据绑定的事件处理方法。protected void Page_Load(object sender, EventArgs e) ddlStatus.DataSource = BookingStatus;ddlStatus.

11、DataBound += new EventHandler(ddlStatus_DataBound);ddlStatus.DataBind();void ddlStatus_DataBound(object sender, EventArgs e) int i = 0;ListControl list = (ListControl)sender; /注意,将 sender 转换成 ListControlforeach (ListItem item in list.Items) i+;item.Value = i.ToString(); 这样,我们使用数组完成了我们期望的效果,虽然这样实现显得有

12、点麻烦,虽然还存在上面提到的不便于使用的问题,但这些问题我们耐心细心一点就能克服,而软件开发几乎从来就没有 100%完美的解决方案,那我们干脆就这样好了。NOTENOTE:在 ddlStatus_DataBound 事件中,引发事件的对象 sender 显然是DropDownList,但是这里却没有将 sender 转换成 DropDownList,而是将它转换成基类型 ListControl。这样做是为了更好地进行代码重用,ddlStatus_DataBound 事件处理方法将不仅限于 DropDownList,对于继承自ListControl 的其他控件,比如 RadioButtonLis

13、t、ListBox 也可以不加改动地使用 ddlStatus_DataBound 方法。如果你对事件绑定还不熟悉,请参考 C#中的委托和事件 一文。这里也可以使用 Dictionary来完成,但都存在类似的问题,就不再举例了。3.3.枚举及其问题枚举及其问题然而不幸的事又发生了. 我们的预订程序分为两部分:一部分为 B/S 端,在 B/S 端可以进行酒店订单的 创建(未提交)、提交(已提交)、取消提交(已取消),另外还可以看到是不是已订妥;一部分为 C/S 端,为酒店的预订中心,它可以进行其他状态的操作。此时,对于整个系统来说,应该有全部的 7 个状态。但对于 B/S 端来说,它只有 未提交、

14、已提交、已取消、已订妥 四个状态,对应的值分别为对应的值分别为 1 1、2 2、3 3、6 6。我们回想一下上面是如何使用数组来解决的,它存在一个缺陷:我们默认地将订单状我们默认地将订单状态值与数组的索引一一对应地联系了起来。态值与数组的索引一一对应地联系了起来。所以在绑定 DropDownList 时,我们采用自增的方式来设定列表项的 Value 值;或者在显示状态时,我们通过 lbStatus.Text = BookingStatusmyOrder.StatusId; 这样的语句来完成。而当这种对应关系被打破时,使用数组的方法就失效了,因为如果不利用数组索引,我们没有额外的地方去存储状态的

15、数字值。此时,我们想到了使用枚举:public enum BookingStatus 未提交 = 1,已提交,已取消,已订妥 = 6我们想在页面输出一个订单的状态时,可以这样:HotelOrder myOrder = GetItem(orderId); /获取一个订单对象lbStatus.Text = (BookingStatus)myOrder.StatusId).ToString(); / 输出文本值我们想更新订单的状态为 “已提交”:myOrder.StatusId = (int)BookingStatus.已提交;当状态为“已取消”时我们想执行某个操作:if(BookingStatus

16、.已取消 = (BookingStatus)myOrder.StatusId)/ Do some action此时,VS 2005 的智能提示已经可以发挥完全作用,当我们在 BookingStatus 后按下“.”时,可以显示出所有的状态值。NOTENOTE:当我们使用枚举存储状态时,myOrder 对象的 StatusId 最好为BookingStatus 枚举类型,而非 int 类型,这样操作会更加便捷一些,但为了和前面使用数组时的情况保持统一,这里 StatusId 仍使用 int 类型。以上三种情况使用枚举都显得非常的流畅,直到我们需要绑定枚举到 DropDownList下拉列表的时候:我们知道,可以绑定到下拉列表的有两类对象,一类是实现了IEnumerable 接口的可枚举集合,比如 ArrayList,String,List;一类是实现了IListSo

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 生活休闲 > 社会民生

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号