ImageVerifierCode 换一换
格式:DOC , 页数:44 ,大小:174.50KB ,
资源ID:7671680      下载积分:10 金币
快捷注册下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

开通VIP
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.zixin.com.cn/docdown/7671680.html】到电脑端继续下载(重复下载【60天内】不扣币)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

开通VIP折扣优惠下载文档

            查看会员权益                  [ 下载后找不到文档?]

填表反馈(24小时):  下载求助     关注领币    退款申请

开具发票请登录PC端进行申请

   平台协调中心        【在线客服】        免费申请共赢上传

权利声明

1、咨信平台为文档C2C交易模式,即用户上传的文档直接被用户下载,收益归上传人(含作者)所有;本站仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。所展示的作品文档包括内容和图片全部来源于网络用户和作者上传投稿,我们不确定上传用户享有完全著作权,根据《信息网络传播权保护条例》,如果侵犯了您的版权、权益或隐私,请联系我们,核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
2、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据,个别因单元格分列造成显示页码不一将协商解决,平台无法对文档的真实性、完整性、权威性、准确性、专业性及其观点立场做任何保证或承诺,下载前须认真查看,确认无误后再购买,务必慎重购买;若有违法违纪将进行移交司法处理,若涉侵权平台将进行基本处罚并下架。
3、本站所有内容均由用户上传,付费前请自行鉴别,如您付费,意味着您已接受本站规则且自行承担风险,本站不进行额外附加服务,虚拟产品一经售出概不退款(未进行购买下载可退充值款),文档一经付费(服务费)、不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
4、如你看到网页展示的文档有www.zixin.com.cn水印,是因预览和防盗链等技术需要对页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有水印标识(原文档上传前个别存留的除外),下载后原文更清晰;试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓;PPT和DOC文档可被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;PDF文档不管是原文档转换或图片扫描而得,本站不作要求视为允许,下载前可先查看【教您几个在下载文档中可以更好的避免被坑】。
5、本文档所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用;网站提供的党政主题相关内容(国旗、国徽、党徽--等)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
6、文档遇到问题,请及时联系平台进行协调解决,联系【微信客服】、【QQ客服】,若有其他问题请点击或扫码反馈【服务填表】;文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“【版权申诉】”,意见反馈和侵权处理邮箱:1219186828@qq.com;也可以拔打客服电话:0574-28810668;投诉电话:18658249818。

注意事项

本文(七、Net中的反射.doc)为本站上传会员【xrp****65】主动上传,咨信网仅是提供信息存储空间和展示预览,仅对用户上传内容的表现方式做保护处理,对上载内容不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知咨信网(发送邮件至1219186828@qq.com、拔打电话4009-655-100或【 微信客服】、【 QQ客服】),核实后会尽快下架及时删除,并可随时和客服了解处理情况,尊重保护知识产权我们共同努力。
温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载【60天内】不扣币。 服务填表

七、Net中的反射.doc

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

2、1.序章,我将通过一个例子来引出反射,获得对反射的第一印象。 2.反射初步、Type类、反射普通类型。(修改中,近期发布...) 3.反射特性(Attribute)。 4.xxxx (待定) 5.... 序章 如果你还没有接触过反射,而我现在就下一堆定义告诉你什么是反射,相信你一定会有当头一棒的感觉。我一直认为那些公理式的定义和概念只有在你充分懂得的时候才能较好的发挥作用。所以,我们先来看一个开发中常遇到的问题,再看看如何利用反射来解决: 在进行数据库设计的过程中,常常会建立一些基础信息表,比如说:全国的城市,又或者订单的状态。假设我们将城市的表,起名为City,它

3、通常包含类似这样的字段: Id Int Identity(1,1) 城市Id Name Varchar(50) 城市名称 ZIP Varchar(10) 城市邮编 ... // 略 这个表将供许多其他表引用。假如我们在建立一个酒店预订系统,那么酒店信息表(Hotel)就会引用此表,用CityId字段来引用酒店所在城市。对于城市(City)表这种情况,表里存放的记录(城市信息)是不定的,意思就是说:我们可能随时会向这张表里添加新的城市(当某个城市的第一家酒店想要加入预订系统时,就需要在City表里新添这家酒店所在的城市)

4、此时,这样的设计是合理的。 1.建表及其问题 我们再看看另外一种情况,我们需要标识酒店预订的状态:未提交、已提交、已取消、受理中、已退回、已订妥、已过期。此时,很多开发人员会在数据库中建立一张小表,叫做BookingStatus(预订状态),然后将如上状态加入进去,就好像这样: 如同城市(City)表一样,在系统的其他表,比如说酒店订单表(HotelOrder)中,通过字段StatusId引用这个表来获取酒店预订状态。然而,几个月以后,虽然看上去和城市表的用法一样,结果却发现这个表只在数据库做联合查询或者 只在程序中调用,却从来不做修改,因为预订流程确定下来后一般是不会

5、变更的。在应用程序中,也不会给用户提供对这个表记录的增删改操作界面。 而在程序中调用这个表时,经常是这种情况:我们需要根据预订状态对订单列表进行筛选。此时通常的做法是使用一个下拉菜单(DropDownList),菜单的数据源(DataSource),我们可以很轻易地通过一个SqlDataReader获得,我们将DropDownList的文本Text设为Status字段,将值Value设为Id字段。 此时,我们应该已经发现问题: 1.如果我们还有航班预订、游船预订,或者其他一些状态,我们需要在数据库中创建很多类似的小表,造成数据库表的数目过多。 2.我们使用DropDown

6、List等控件获取表内容时,需要连接到数据库进行查询,潜在地影响性能。 同时,我们也注意到三点: 1.此表一般会在数据库联合查询中使用到。假设我们有代表酒店订单的HotelOrder表,它包含代表状态的StatusId字段,我们的查询可能会像这样:Select *, (Select Status From BookingStatus Where Id = HotelOrder.StatusId) as Status From HotelOrder。 2.在应用程序中,此表经常作为DropDownList或者其他List控件的数据源。 3.这个表几乎从不改动。 2.数组及其

7、问题 意识到这样设计存在问题,我们现在就想办法解决它。我们所想到的第一个办法是可以在程序中创建一个数组来表示预订状态,这样我们就可以删掉BookingStatus状态表(注意可以这样做是因为BookingStatus表的内容确定后几乎从不改动)。 string[] BookingStatus = { "NoUse", "未提交","已提交","已取消","受理中","已退回","已订妥","已过期" }; // 注意数组的0号元素仅仅是起一个占位作用,以使程序简洁。因为StatusId从1开始。 我们先看它解决了什么:上面提到的问题1、问题2都解决了,既不

8、需要在数据库中创建表,又无需连接到数据库进行查询。 我们再看看当我们想要用文本显示酒店的预订时,该怎么做(假设有订单类HotelOrder,其属性StatusId代表订单状态,为int类型 )。 // GetItem用于获取一个酒店订单对象, orderId为int类型,代表订单的Id HotelOrder myOrder = GetItem(orderId); lbStatus.Text = BookingStatus[myOrder.StatusId]; //lbStatus是一个Label控件 目前为止看上去还不错,现在我们需要进行一个操作,将订单的状态改为“受理

9、中”。 myOrder.StatusId = 4; 很不幸,我们发现了使用数组可能带来的第一个问题:不方便使用,当我们需要更新订单的状态值时,我们需要去查看BookingStatus数组的定义(除非你记住所有状态的数字值),然后根据状态值在数组中的位置来给对象的属性赋值。 我们再看另一个操作,如果某个订单的状态为“已过期”,就要对它进行删除: if(BookingStatus[myOrder.StatusId]=="已过期"){ DeleteItem(myOrder); // 删除订单 } 此时的问题和上面的类似:我们需要手动输入字符串“已过期

10、此时Vs2005 的智能提示发挥不了任何作用,如果我们不幸将状态值记错,或者手误打错,就将导致程序错误,较为稳妥的做法还是按下F12导向到BookingStatus数组的定义,然后将“已过期”复制过来。 现在,我们再看看如何来绑定到一个DropDownList下拉列表控件(Id为ddlStatus)上。 ddlStatus.DataSource = BookingStatus; ddlStatus.DataBind(); 但是我们发现产生的HTML代码是这样: 我们看到,列表项的value值与text值相同,这显然不是我们

12、想要的,怎么办呢?我们可以给下拉列表写一个数据绑定的事件处理方法。 protected void Page_Load(object sender, EventArgs e) { ddlStatus.DataSource = BookingStatus; ddlStatus.DataBound += new EventHandler(ddlStatus_DataBound); ddlStatus.DataBind(); } void ddlStatus_DataBound(object sender, EventArgs e) { i

13、nt i = 0; ListControl list = (ListControl)sender; //注意,将sender转换成ListControl foreach (ListItem item in list.Items) { i++; item.Value = i.ToString(); } } 这样,我们使用数组完成了我们期望的效果,虽然这样实现显得有点麻烦,虽然还存在上面提到的不便于使用的问题,但这些问题我们耐心细心一点就能克服,而软件开发几乎从来就没有100%完美的解决方案,那我们干脆就这样

14、好了。 NOTE:在ddlStatus_DataBound事件中,引发事件的对象sender显然是DropDownList,但是这里却没有将sender转换成DropDownList,而是将它转换成基类型ListControl。这样做是为了更好地进行代码重用,ddlStatus_DataBound事件处理方法将不仅限于 DropDownList,对于继承自ListControl的其他控件,比如RadioButtonList、ListBox也可以不加改动地使用ddlStatus_DataBound方法。 如果你对事件绑定还不熟悉,请参考 C#中的委托和事件 一文。

15、 这里也可以使用Dictionary来完成,但都存在类似的问题,就不再举例了。 3.枚举及其问题 然而不幸的事又发生了... 我们的预订程序分为两部分:一部分为B/S端,在B/S端可以进行酒店订单的 创建(未提交)、提交(已提交)、取消提交(已取消),另外还可以看到是不是已订妥;一部分为C/S端,为酒店的预订中心,它可以进行其他状态的操作。 此时,对于整个系统来说,应该有全部的7个状态。但对于B/S端来说,它只有 未提交、已提交、已取消、已订妥 四个状态,对应的值分别为 1、2、3、6。 我们回想一下上面是如何使用数组来解决的,它存在一个缺陷:我

16、们默认地将订单状态值与数组的索引一一对应地联系了起来。 所以在绑定DropDownList时,我们采用自增的方式来设定列表项的Value值;或者在显示状态时,我们通过lbStatus.Text = BookingStatus[myOrder.StatusId]; 这样的语句来完成。而当这种对应关系被打破时,使用数组的方法就失效了,因为如果不利用数组索引,我们没有额外的地方去存储状态的数字值。 此时,我们想到了使用枚举: public enum BookingStatus { 未提交 = 1, 已提交, 已取消, 已订妥 = 6 }

17、 我们想在页面输出一个订单的状态时,可以这样: HotelOrder myOrder = GetItem(orderId); //获取一个订单对象 lbStatus.Text = ((BookingStatus)myOrder.StatusId).ToString(); // 输出文本值 我们想更新订单的状态为 “已提交”: myOrder.StatusId = (int)BookingStatus.已提交; 当状态为“已取消”时我们想执行某个操作: if(BookingStatus.已取消 == (BookingStatus)myOrder.

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

19、是实现了IEnumerable接口的可枚举集合,比如ArrayList,String[],List;一类是实现了IListSource的数据源,比如DataTable,DataSet。 NOTE:实际上IListSource接口的GetList()方法返回一个IList接口,IList接口又继承了IEnumerable接口。由此看来,IEnumerable是实现可枚举集合的基础,在我翻译的一篇文章 C#中的枚举器 中,对这个主题做了详细的讨论。 可我们都知道:枚举enum是一个基本类型,它不会实现任何的接口,那么我们下来该如何做呢? 4.使用反射遍历枚举字段 最笨也是

20、最简单的办法,我们可以先创建一个GetDataTable方法,此方法依据枚举的字段值和数字值构建一个DataTable,最后返回这个构建好的DataTable: private static DataTable GetDataTable() { DataTable table = new DataTable(); table.Columns.Add("Name", Type.GetType("System.String")); //创建列 table.Columns.Add("Value", Type.GetType("System.I

21、nt32")); //创建列 DataRow row = table.NewRow(); row[0] = BookingStatus.未提交.ToString(); row[1] = 1; table.Rows.Add(row); row = table.NewRow(); row[0] = BookingStatus.已提交.ToString(); row[1] = 2; table.Rows.Add(row); row = table.NewRow();

22、 row[0] = BookingStatus.已取消.ToString(); row[1] = 3; table.Rows.Add(row); row = table.NewRow(); row[0] = BookingStatus.已订妥.ToString(); row[1] = 6; table.Rows.Add(row); return table; } 接下来,为了方便使用,我们再创建一个专门采用这个DataTable来设置列表控件的方法SetListCountrol():

23、 // 设置列表 public static void SetListControl(ListControl list) { list.DataSource = GetDataTable(); // 获取DataTable list.DataTextField = "Name"; list.DataValueField = "Value"; list.DataBind(); } 现在,我们就可以在页面中这样去将枚举绑定到列表控件: protected void Page_Load(object sender, E

24、ventArgs e) { SetListControl(ddlStatus); // 假设页面中已有ID为ddlStatus 的DropDownList } 如果所有的枚举都要通过这样去绑定到列表,我觉得还不如在数据库中直接建表,这样实在是太麻烦了,而且我们是根据枚举的文本和值去HardCoding出一个DataTable的: DataRow row = table.NewRow(); row[0] = BookingStatus.未提交.ToString(); row[1] = 1; table.Rows.Add(row); row = table

25、NewRow(); row[0] = BookingStatus.已提交.ToString(); row[1] = 2; table.Rows.Add(row); row = table.NewRow(); row[0] = BookingStatus.已取消.ToString(); row[1] = 3; table.Rows.Add(row); row = table.NewRow(); row[0] = BookingStatus.已订妥.ToString(); row[1] = 6; table.Rows.Add(row); 这个时候,我们想有没有

26、办法通过遍历来实现这里?如果想要遍历这里,首先,我们需要一个包含枚举的每个字段信息的对象,这个对象至少包含两条信息,一个是字段的文本(比如“未提交”),一个是字段的数字型值(比如1),我们暂且管这个对象叫做field。其次,应该存在一个可遍历的、包含了字段信息的对象(也就是filed) 的集合,我们暂且管这个集合叫做enumFields。 那么,上面就可以这样去实现: foreach (xxxx field in enumFields) { DataRow row = table.NewRow(); row[0] = field.Name; /

27、/ 杜撰的属性,代表 文本值(比如“未提交”) row[1] = filed.intValue; // 杜撰的属性,代表 数字值(比如1) table.Rows.Add(row); } 这段代码很不完整,我们注意到 xxxx,它应该是封装了字段信息(或者叫元数据metadata)的对象的类型。而对于enumFields,它的类型应该是xxxx这个类型的集合。这段代码是我们按照思路假想和推导出来的。实际上,.Net 中提供了 Type类 和 System.Reflection命名空间来帮助解决我们现在的问题。 我在后面将较详细地介绍 Type类,现在

28、只希望你能对反射有个第一印象,所以只简略地作以说明:Type抽象类提供了访问类型元数据的能力,当你实例化了一个Type对象后,你可以通过它的属性和方法,获取类型的元数据信息,或者进一步获得该类型的成员的元数据。注意到这里,因为Type对象总是基于某一类型的,并且它是一个抽象类,所以我们在创建Type类型时,必须要提供 类型,或者类型的实例,或者类型的字符串值(Part.2会说明)。 创建Type对象有很多种方法,本例中,我们使用typeof操作符来进行,并传递BookingStatus枚举: Type enumType = typeof(BookingStatus); 然后,

29、我们应该想办法获取 封装了字段信息的对象 的集合。Type类提供 GetFields()方法来实现这一过程,它返回一个 FieldInfo[] 数组。实际上,也就是上面我们enumFields集合的类型。 FieldInfo[] enumFields = enumType.GetFields(); 现在,我们就可以遍历这一集合: foreach (FieldInfo field in enumFields) { if (!field.IsSpecialName) { DataRow row = table.NewRow();

30、 row[0] = field.Name; // 获取字段文本值 row[1] = Convert.ToInt32(myField.GetRawConstantValue()); // 获取int数值 table.Rows.Add(row); } } 这里field的Name属性获取了枚举的文本,GetRawConstantValue()方法获取了它的int类型的值。 我们看一看完整的代码: private static DataTable GetDataTable() { Type enumType =

31、typeof(BookingStatus); // 创建类型 FieldInfo[] enumFields = enumType.GetFields(); //获取字段信息对象集合 DataTable table = new DataTable(); table.Columns.Add("Name", Type.GetType("System.String")); table.Columns.Add("Value", Type.GetType("System.Int32")); // 遍历集合 foreach

32、 (FieldInfo field in enumFields) { if (!field.IsSpecialName) { DataRow row = table.NewRow(); row[0] = field.Name; row[1] = Convert.ToInt32(field.GetRawConstantValue()); //row[1] = (int)Enum.Parse(enumType, field.Name); //也可以这样

33、 table.Rows.Add(row); } } return table; } 注意,SetListControl()方法依然存在并有效,只是为了节省篇幅,我没有复制过来,它的使用和之前是一样的,我们只是修改了GetDataTable()方法。 5.使用泛型来达到代码重用 观察上面的代码,如果我们现在有另一个枚举,叫做TicketStatus,那么我们要将它绑定到列表,我们唯一需要改动的就是这里: Type enumType = typeof(BookingStatus); //将BookingStatus改作Tic

34、ketStatus 既然这样,我们何不定义一个泛型类来进行代码重用呢?我们管这个泛型类叫做EnumManager。 public static class EnumManager { private static DataTable GetDataTable() { Type enumType = typeof(TEnum); // 获取类型对象 FieldInfo[] enumFields = enumType.GetFields(); DataTable table = ne

35、w DataTable(); table.Columns.Add("Name", Type.GetType("System.String")); table.Columns.Add("Value", Type.GetType("System.Int32")); //遍历集合 foreach (FieldInfo field in enumFields) { if (!field.IsSpecialName) { DataRow row

36、 table.NewRow(); row[0] = field.Name; row[1] = Convert.ToInt32(field.GetRawConstantValue()); //row[1] = (int)Enum.Parse(enumType, field.Name); 也可以这样 table.Rows.Add(row); } } return table; } public

37、static void SetListControl(ListControl list) { list.DataSource = GetDataTable(); list.DataTextField = "Name"; list.DataValueField = "Value"; list.DataBind(); } } OK,现在一切都变得简便的多,以后,我们再需要将枚举绑定到列表,只要这样就行了(ddl开头的是DropDownList,rbl开头的是RadioButtonList): Enum

38、Manager.SetListControl(ddlBookingStatus); EnumManager.SetListControl(rblTicketStatus); NOTE:如果你对泛型不熟悉,请参阅 C# 中的泛型 一文。上面的实现并没有考虑到性能的问题,仅仅为了引出反射使用的一个实例。 6 .Net 中反射的一个范例。 不管是VS2005的智能提示,还是修改变量名时的重构功能,都使用了反射功能。在.Net FCL中,也经常能看到反射的影子,这里就向大家演示一个最常见的例子。大家知道,在CLR中一共有两种类

39、型,一种是值类型,一种是引用类型。声明一个引用类型的变量并对类型实例化,会在应用程序堆(Application Heap)上分配内存,创建对象实例,然后将对象实例的内存地址返回给变量,变量保存的是内存地址,实际相当于一个指针;声明一个值类型的实例变量,则会将它分配在线程堆栈(Thread Stack)上,变量本身包含了值类型的所有字段。 现在假设我们需要比较两个对象是否相等。当我们比较两个引用类型的变量是否相等时,我们比较的是这两个变量所指向的是不是堆上的同一个实例(内存地址是否相同)。而当我们比较两个值类型变量是否相等时,怎么做呢?因为变量本身就包含了值类型所有的字段(数据),所以在比

40、较时,就需要对两个变量的字段进行逐个的一对一的比较,看看每个字段的值是否都相等,如果任何一个字段的值不等,就返回false。 实际上,执行这样的一个比较并不需要我们自己编写代码,Microsoft已经为我们提供了实现的方法:所有的值类型继承自 System.ValueType, ValueType和所有的类型都继承自System.Object ,Object提供了一个Equals()方法,用来判断两个对象是否相等。但是ValueType覆盖了Object的Equals()方法。当我们比较两个值类型变量是否相等时,可以调用继承自ValueType类型的Equals()方法。 publ

41、ic struct ValPoint { public int x; public int y; } static void Main(string[] args) { bool result; ValPoint A1; A1.x = A1.y = 3; ValPoint B1 = A1; // 复制A的值给B result = A1.Equals(B1); Console.WriteLine(result); // 输出 True; } 你有没有想到当调用Equ

42、als()方法时会发生什么事呢?前面我们已经提到如果是值类型,会对两个变量的字段进行逐个的比较,看看每个字段的值是否都相等,但是如何获取变量的所有字段,遍历字段,并逐一比较呢?此时,你应该意识到又到了用到反射的时候了,让我们使用reflector来查看ValueType类的Equals()方法,看看微软是如何做的吧: public override bool Equals(object obj) { if (obj == null) { return false; } RuntimeType type = (RuntimeType)base.

43、GetType(); RuntimeType type2 = (RuntimeType)obj.GetType(); if (type2 != type) { return false; } object a = this; if (CanCompareBits(this)) { return FastEqualsCheck(a, obj); } // 获取所有实体字段 FieldInfo[] fields = type.GetFields(BindingFlags.NonPubli

44、c | BindingFlags.Public | BindingFlags.Instance); // 遍历字段,判断字段值是否相等 for (int i = 0; i < fields.Length; i++) { object obj3 = ((RtFieldInfo)fields[i]).InternalGetValue(a, false); object obj4 = ((RtFieldInfo)fields[i]).InternalGetValue(obj, false); if (obj3 == null) {

45、 if (obj4 != null) { return false; } } else if (!obj3.Equals(obj4)) { return false; } } return true; } 注意到上面加注释的那两段代码,可以看到当对值变量进行比较时,是会使用反射来实现。反射存在着性能不佳的问题(不仅如此,还存在着很多的装箱操作),由此可见,在值类型上调用Equals()方法开销是会很大的。但是这个例子仅仅为了说明反射的用

46、途,我想已经达到了目的。上面的代码不能完全理解也不要紧,后面会再提到。 7.小结 看到这里,你应该对反射有了一个初步的概念(或者叫反射的一个用途):反射是一种宽泛的叫法,它通过 System.Reflection 命名空间 并 配合 System.Type 类,提供了在运行时(Runtime)对于 类型和对象(及其成员)的基本信息 以及 元数据(metadata)的访问能力。 .Net 中的反射(查看基本类型信息) - Part.2反射概述 和Type类 1.反射的作用 简单来说,反射提供这样几个能力:1、查看和遍历类型(及其成员)的基本信息和程序集元数据(metadata)

47、2、迟绑定(Late-Binding)方法和属性。3、动态创建类型实例(并可以动态调用所创建的实例的方法、字段、属性)。序章中,我们所采用的那个例子,只是反射的一个用途:查看类型成员信息。接下来的几个章节,我们将依次介绍反射所提供的其他能力。 2.获取Type对象实例 反射的核心是Type类,这个类封装了关于对象的信息,也是进行反射的入口。当你获得了关于类型的Type对象后,就可以根据Type提供的属性和方法获取这个类型的一切信息(方法、字段、属性、事件、参数、构造函数等)。我们开始的第一步,就是获取关于类型的Type实例。获取Type对象有两种形式,一种是获取当前加载程序集中的类型

48、Runtime),一种是获取没有加载的程序集的类型。 我们先考虑Runtime时的Type,一般来说有三种获取方法: 2.1使用Type类提供的静态方法GetType() 比如我们想要获得Stream类型的Type实例,则可以这样: Type t = Type.GetType("System.IO.Stream"); txtOutput.Text = t.ToString(); 注意到GetType方法接受字符串形式的类型名称。 2.2 使用 typeof 操作符 也可以使用C# 提供的typeof 操作符来完成这一过程: // 如果在页首写入了us

49、ing System.IO; 也可以直接用 typeof(Stream); Type t = typeof(System.IO.Stream); 这时的使用有点像泛型,Stream就好像一个类型参数一样,传递到typeof操作符中。 2.3 通过类型实例获得Type对象 我们还可以通过类型的实例来获得: String name = "Jimmy Zhang"; Type t = name.GetType(); 使用这种方法时应当注意,尽管我们是通过变量(实例)去获取Type对象,但是Type对象不包含关于这个特定对象的信息,仍是保存对象的类型(String)的信

50、息。 3.Type类型 及 Reflection命名空间的组织结构 到现在为止,我已经多次提过Type封装了类型的信息,那么这些类型信息都包含什么内容呢?假设我们现在有一个类型的实例,它的名字叫做 demo,我们对它的信息一无所知,并通过下面代码获取了对于它的Type实例: // 前面某处的代码实例化了demo对象 Type t = demo.GetType(); 现在,我们期望 t 包含了关于 demo 的哪些信息呢? 3.1 demo的类型的基本信息 •我们当然首先想知道 demo 是什么类型的,也就是 demo 的类型名称。 •我们还想知道该类型位于什么命

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服