威尼斯人线上娱乐

【威尼斯人线上娱乐】获取音信详细,面向对象程序设计进阶

11 4月 , 2019  

序言:反射(Reflection)是.NET提须要开发者的三个强劲工具,即便作为.NET框架的使用者,很多时候不会用到反射。但在有个别情状下,特别是在付出一些基础框架或国有类库时,使用反射会使系统框架结构更灵敏。

引言

反射是.Net提需要我们的1件强力武器,就算超越3/陆情形下大家不常用到反射,就算大家大概也不需求精通它,但对反射的施用作以起初询问在此后的支付中可能会怀有协助。

反射是一个宏大的话题,牵扯到的知识点也很多,包罗程序集、自定义本性、泛型等,想要完全驾驭它那2个正确。本文仅仅对反射做一个大致介绍,关于它越来越深邃的始末,要求在实践中慢慢控制。本文将分成下边几个部分介绍.Net中的反射:

  1. 序章,小编将通过1个例子来引出反射,获得对反射的第3影象。
  2. 反射开始、Type类、反射普通品种。(修改中,近日公布…)
  3. 反射性格(Attribute)。
  4. xxxx (待定)

摘 要

[.net面向对象程序设计进阶]反射(Reflection)利用反射技术完结动态编程

 

序章

比方您还并未有接触过反射,而本人前几日就下一批定义告诉你怎么着是反光,相信您早晚会有3只壹棒的觉得。小编直接认为那三个公理式的概念和概念唯有在您丰盛领悟的时候才能较好的发挥成效。所以,大家先来看一个开发中常境遇的题材,再看看怎样利用反射来消除:

在进展数据库设计的进度中,常常会树立部分基础音讯表,比如说:全国的城池,又或然订单的图景。假若大家将城市的表,起名字为City,它日常包括类似那样的字段:

Id     Int Identity(1,1) 城市Id
Name   Varchar(50)           城市名称
ZIP    Varchar(十)           城市邮政编码
… // 略

以此表将供广大别样表引用。如果我们在建立贰个酒吧预约系统,那么商旅信息表(Hotel)就会引用此表,用CityId字段来引用饭店所在城市。对于都市(City)表那种场所,表里存放的记录(城市消息)是不定的,意思正是说:我们恐怕随时会向那张表里添加新的城市(当有个别城市的首先家酒吧想要参加预约系统时,就须求在City表里新添这家旅社所在的城池)。此时,那样的规划是合理合法的。

反射,3个很有用且有趣的特色。当动态创立有些项目标实例或是调用方法也许访问对象成员时一般会用到它,它是依据程序集及元数据而工作的,所以那一章大家来研讨一下程序集、反射怎么着行事、如何动态创建类型及对象等城门失火文化,甚至可以动态创立程序集。

本节导读:本节任重(英文名:rèn zhòng)而道远介绍怎么样是.NET反射脾气,.NET反射能为大家做些什么,最终介绍两种常用的反光的落到实处方式,通过对反射性特的刺探,能够布置出极度实用的依据反射的编制程序情势。

在付出中,我们常常会蒙受比如说有个别情形值在概念好后大概从未改动,那时候使用数据库就展现略微多余了。首先想到的1个办法大概是在程序中开创2个数组来表示,此时,大家相遇了应用数组恐怕带来的率先个难点:不方便使用。当数组结构改变时,可能意味着全数应用过此数组的地点的目录都产生了改变,那是大家不想看到的。

1.建表及其难题

我们再看看其余一种状态,大家供给标识旅社预约的情况:未提交、已交由、已收回、受理中、已退回、已订妥、已过期。此时,很多开发人士会在数据库中国建工业总会公司立一张小表,叫做BookingStatus(预约景况),然后将如上情形进入进来,就类似那样:

威尼斯人线上娱乐 1

就像是城市(City)表一样,在系统的任何表,比如说饭店订单表(HotelOrder)中,通过字段StatusId引用这些表来获取宾馆预约情状。可是,多少个月之后,纵然看起来和城市表的用法一样,结果却发现那么些表只在数据库做联合查询大概只在程序中调用,却不曾做修改,因为预约流程规定下来后1般是不会改变的。在应用程序中,也不会给用户提供对那几个表记录的增加和删除改操作界面。

而在先后中调用那几个表时,平常是那种气象:大家要求依据预约情形对订单列表进行筛选。此时一般性的做法是利用1个下拉菜单(DropDownList),菜单的数据源(DataSource),我们得以很自由地通过一个SqlDataReader得到,大家将DropDownList的文本Text设为Status字段,将值Value设为Id字段。

那儿,咱们应该早就意识难点:

  1. 若是大家还有航班预定、游船预定,也许其余一些情况,大家必要在数据库中开创很多近似的小表,造成数据库表的数目过多。
  2. 大家利用DropDownList等控件获取表内容时,须求一而再到数据库进行询问,潜在地影响属性。

与此同时,大家也注意到3点:

  1. 此表①般会在数据库联合查询中使用到。假设我们有表示酒店订单的HotelOrder表,它包涵代表景况的StatusId字段,大家的查询也许会像这么:Select
    *, (Select Status From BookingStatus Where Id =
    HotelOrder.StatusId) as Status From HotelOrder。
  2. 在应用程序中,此表平日作为DropDownList也许别的List控件的数据源。
  3. 那么些表大致从不改动。

先是节 应用程序域与程序集

读前须求:

那时,大家能够选取枚举:

2.数组及其难点

察觉到那样设计存在难点,大家明天就想艺术缓解它。我们所想到的第三个方法是足以在先后中创制一个数组来表示预定意况,那样我们就足以删掉BookingStatus状态表(注意能够如此做是因为BookingStatus表的内容规定后差不多向来不改动)。

string[] BookingStatus = {  
   “NoUse”,
“未提交”,”已提交”,”已取消”,”受理中”,”已退回”,”已订妥”,”已过期”
};     //
注意数组的0号成分仅仅是起二个占位功能,以使程序简洁。因为StatusId从一发轫。

我们先看它化解了如何:上面提到的难点一、难点2都解决了,既不必要在数据库中创设表,又无需再三再四到数据库实行询问。

咱俩再看看当大家想要用文件显示旅社的预购时,该怎么办(假使有订单类HotelOrder,其天性StatusId代表订单状态,为int类型
)。

// GetItem用于获取二个酒家订单对象, orderId为int类型,代表订单的Id
HotelOrder myOrder = GetItem(orderId);
lbStatus.Text = BookingStatus[myOrder.StatusId]; 
//lbStatus是一个Label控件

最近截至看上去基本上能用,未来大家要求进行八个操作,将订单的动静改为“受理中”。

myOrder.StatusId = 4;

很不幸,大家发现了选择数组或者带来的第二个难点:不方便使用,当大家要求更新订单的处境值时,大家供给去查看BookingStatus数组的概念(除非你记住全体景况的数字值),然后遵照意况值在数组中的地方来给目的的质量赋值。

大家再看另八个操作,若是有个别订单的景观为“已过期”,就要对它进行删减:

if(BookingStatus[myOrder.StatusId]==”已过期”){
    DeleteItem(myOrder);     // 删除订单
}

那儿的标题和下边包车型客车近乎:我们必要手动输入字符串“已过期”,此时Vs二零零七的智能提醒发挥不了任何效用,假如我们不幸将状态值记错,可能手误打错,就将促成程序错误,较为妥帖的做法还是按下F1二导向到BookingStatus数组的概念,然后将“已过期”复制过来。

最近,大家再看看怎么着来绑定到五个DropDownList下拉列表控件(Id为ddlStatus)上。

ddlStatus.DataSource = BookingStatus;
ddlStatus.DataBind();

唯独大家发现产生的HTML代码是那样:

<select name=”ddlStatus” id=”ddlStatus”>
    <option value=”未提交”>未提交</option>
    <option value=”已提交”>已提交</option>
    <option value=”已取消”>已取消</option>
    <option value=”受理中”>受理中</option>
    <option value=”已退回”>已退回</option>
    <option value=”已订妥”>已订妥</option>
    <option value=”已过期”>已过期</option>
</select>

咱俩看到,列表项的value值与text值相同,那分明不是大家想要的,如何是好吧?大家得以给下拉列表写1个数量绑定的事件处理方法。

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) {
    int i = 0;
    ListControl list = (ListControl)sender;
//注意,将sender转换成ListControl
    foreach (ListItem item in list.Items) {
       i++;
       item.Value = i.ToString();         
    }
}

诸如此类,大家采用数组完毕了作者们目的在于的成效,就算那样完成显得略微麻烦,即便还留存下边提到的不便宜使用的难点,但那几个难题大家耐心细致一点就能征服,而软件开发大约根本就从未百分百健全的消除方案,这大家简直就好像此好了。

NOTE:在ddlStatus_DataBound事件中,引发事件的指标sender显明是DropDownList,不过此地却不曾将sender转换到DropDownList,而是将它转换来基类型ListControl。那样做是为了越来越好地进行代码重用,ddlStatus_DataBound事件处理方法将不仅限于
DropDownList,对于继续自ListControl的任何控件,比如RadioButtonList、ListBox也足以不加改动地利用ddlStatus_DataBound方法。

    假设你对事件绑定还不熟谙,请参考
C#中的委托和事件
一文。

    那里也足以利用Dictionary<String,
Int>来完成,但都存在类似的题材,就不再举例了。

通过本种类的日前章节,大家曾经知晓,Windows为每一种进程分配独立的内部存款和储蓄器空间地址,各种进度之间不能一贯互动拜访。Windows对.NET的支撑是以宿主和COM的情势实现的,基于.NET平台语言完成的代码文件使用Windows
PE的文件格式,CL卡宴其实正是COM,相当于多少个虚拟机(当然这几个虚拟机能够配备到自由支持它的类别环境中),在安装.NET
Framework时,CLEscort的机件与别的COM1样在Windows系统中颇具平等的待遇,当CL福特Explorer运维初步化时会创制一个运用程序域,应用程序域是1组先后集的逻辑容器,它会趁机进度的告壹段落而被卸载销毁,CL福睿斯把程序代码所须求的主次集加载到日前(或钦赐的)应用程序域内。CL普拉多能够以其先导化时创制的行使程序域为根基再次创下造别的的新利用程序域,多个应用程序域中的代码不能够直接待上访问,当然能够经过“中介”实行数量传送。新的程序域创造完后CL悍马H二完全能够卸载它,以一头形式调用AppDomain.Unload方法即可,调用此格局后,CLBMWX三会挂起近来进程中的全体线程,接着查找并暂停止运输转在快要卸载的程序域内的线程,然后开始展览垃圾回收,最终主线程复苏运行。

[.net面向对象编制程序基础]类的积极分子

    public enum BookingStatus
    {
        未提交 =1,
        已提交,
        已取消,
        已定妥 = 6
    }

3.枚举会同难点

可是不幸的事又产生了…
我们的订座程序分成两部分:1部分为B/S端,在B/S端能够拓展酒馆订单的
创立(未提交)、提交(已提交)、撤废提交(已打消),其它还足以见到是否已订妥;一部分为C/S端,为旅社的订座中央,它能够拓展任何意况的操作。

此刻,对于任何种类的话,应该有全方位的九个状态。但对此B/S端来说,它唯有未提交、已交给、已吊销、已订妥 八个意况,对应的值分别为 1、2、3、6。

大家回想一下方面是怎么着行使数组来化解的,它存在贰个欠缺:大家私下认可地将订单状态值与数组的索引一壹对应地关系了4起。

之所以在绑定DropDownList时,大家选择自增的不2秘籍来设定列表项的Value值;也许在显示状态时,大家透过lbStatus.Text
= BookingStatus[myOrder.StatusId];
那样的语句来完毕。而当那种对应关系被打破时,使用数组的秘籍就失效了,因为如果不选拔数组索引,我们一贯不额外的地点去存款和储蓄状态的数字值。

此时,大家想到了利用枚举:

public enum BookingStatus {
    未提交 = 1,
    已提交,
    已取消,
    已订妥 = 6
}

咱俩想在页面输出多个订单的景色时,能够那样:

HotelOrder myOrder = GetItem(orderId);         //获取三个订单对象
lbStatus.Text = ((BookingStatus)myOrder.StatusId).ToString(); //
输出文本值

我们想翻新订单的处境为 “已交付”:

myOrder.StatusId = (int)BookingStatus.已提交;

当状态为“已收回”时大家想进行有个别操作:

if(BookingStatus.已取消 == (BookingStatus)myOrder.StatusId){
    // Do some action
}

此刻,VS 二〇〇七的智能提示已经得以公布完全意义,当大家在BookingStatus后按下“.”时,能够显得出富有的境况值。

NOTE:当大家运用枚举存款和储蓄状态时,myOrder对象的StatusId最棒为BookingStatus枚举类型,而非int类型,那样操作会特别便利一些,但为了和前边使用数组时的场合保持统一,那里StatusId仍利用int类型。

以上二种处境使用枚举都来得卓殊的意味深长,直到我们须要绑定枚举到DropDownList下拉列表的时候:大家知晓,能够绑定到下拉列表的有两类对象,一类是兑现了IEnumerable接口的可枚举集合,比如ArrayList,String[],List<T>;1类是实现了IListSource的数据源,比如DataTable,DataSet。

NOTE:实际上IListSource接口的GetList()方法再次来到三个IList接口,IList接口又接二连三了IEnumerable接口。由此看来,IEnumerable是达成可枚举集合的基础,在自个儿翻译的一篇小说
C#中的枚举器
中,对那么些宗旨做了详尽的座谈。

可我们都晓得:枚举enum是贰个主干项目,它不会兑现其余的接口,那么大家下去该如何做啊?

别的Windows程序都能够寄宿CL宝马7系,1台机上能够安装几个本子的CLLAND。Windows在起步二个托管的程序时会先运营MSCorEE.dll中的三个主意,该方式在里面依据一个托管的可执行文件消息来加载相应版本的CL奥迪Q5,CL宝马X五初阶完毕以往,将先后集加载到利用程序域,最终CL奥迪Q5检查程序集的CLKoleos头消息找到Main方法并进行它。

1.什么是.NET反射?

在其实使用中,恐怕须求用户下拉挑选那些情形值,那时就必要我们把枚举绑定到下拉框上(此处以Combobox为例)了。大家清楚,可以绑定到下拉框列表的有三种类型:壹种是落到实处了IEnumerable接口的可枚举类型,比如ArrayList,String[],List<T>;壹类是落到实处了IListSource的数据源,比如DataTable,DataSet。

肆.运用反射遍历枚举字段

最笨也是最简单易行的法子,我们得以先创制一个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.Int32”));      
//创建列

     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();
     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;
 }

接下去,为了方便使用,大家再次创下制3个特地使用那一个DataTable来安装列表控件的不二秘诀SetListCountrol():

// 设置列表
 public static void SetListControl(ListControl list) {
     list.DataSource = GetDataTable();      // 获取DataTable
     list.DataTextField = “Name”;
     list.DataValueField = “Value”;
     list.DataBind();
 }

现今,我们就足以在页面中那样去将枚举绑定到列表控件:

protected void Page_Load(object sender, EventArgs e)
{
    SetListControl(ddlStatus);   // 假使页面中已有ID为ddlStatus
的DropDownList
}

假如持有的枚举都要通过那样去绑定到列表,小编认为还不及在数据库中一贯建表,那样实在是太费事了,而且大家是基于枚举的文本和值去HardCoding出2个DataTable的:

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();
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);

以此时候,大家想有没有主意通过遍历来兑现那里?假若想要遍历那里,首先,大家须求1个富含枚举的各种字段新闻的对象,那么些指标至少含有两条新闻,2个是字段的文本(比如“未提交”),一个是字段的数字型值(比如一),我们临时管这几个指标叫做田野先生。其次,应该留存贰个可遍历的、包括了字段音讯的靶子(也正是filed)
的联谊,我们一时管那一个集合叫做enumFields。

那么,上边就能够如此去落到实处:

foreach (xxxx field in enumFields)
{
    DataRow row = table.NewRow();
    row[0] = 田野(field).Name;         // 杜撰的习性,代表
文本值(比如“未提交”)
    row[1] = filed.intValue;     // 杜撰的质量,代表 数字值(比如一)

    table.Rows.Add(row);
}

那段代码很不完全,大家注意到
xxxx,它应该是包裹了字段消息(可能叫元数据metadata)的目标的门类。而对此enumFields,它的项目应该是xxxx这么些项目标聚集。那段代码是大家依照思路假想和演绎出来的。实际上,.Net
中提供了 Type类 和 System.Reflection命名空间来协理缓解大家明天的难题。

自小编在前面将较详细地介绍
Type类,现在只期待您能对反射有个第一影象,所以只简简单单地作以表达:Type抽象类提供了拜访类型元数据的能力,当您实例化了八个Type对象后,你能够经过它的品质和方法,获取项目标元数据音信,或许进一步取得该项指标积极分子的元数据。只顾到此处,因为Type对象总是基于某1类其他,并且它是八个抽象类,之所以大家在成立Type类型时,供给求提供
类型,也许项目标实例,也许项指标字符串值(Part.2会表明)。

始建Type对象有很七种主意,本例中,大家选择typeof操作符来拓展,并传递BookingStatus枚举:

Type enumType = typeof(BookingStatus);

接下来,我们相应想办法得到 封装了字段新闻的靶子 的聚众。Type类提供
GetFields()方法来达成那1历程,它回到2个 FieldInfo[]
数组。实际上,也就是地方我们enumFields集合的连串。

FieldInfo[] enumFields = enumType.GetFields();

于今,我们就能够遍历那壹汇合:

foreach (FieldInfo field in enumFields)
{
    if (!field.IsSpecialName)
    {
       DataRow row = table.NewRow();
       row[0] = 田野.Name;     // 获取字段文本值
       row[1] = Convert.ToInt32(myField.GetRawConstantValue()); //
获取int数值
       table.Rows.Add(row);
    }
}

那边田野(field)的Name属性获取了枚举的公文,GetRawConstantValue()方法取得了它的int类型的值。

我们看1看完整的代码:

private static DataTable GetDataTable() {

     Type enumType = 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 (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, 田野同志.Name);
//也得以这么

            table.Rows.Add(row);
        }
     }

     return table;
 }

小心,SetListControl()方法照旧存在并实用,只是为着省去篇幅,作者并未有复制过来,它的运用和事先是如出一辙的,我们只是修改了GetDataTable()方法。

 

反射是.NET三个重大的性状,《CL陆风X8viaC#》壹书中对.NET反射的解释为:在大家应用程序中使用元数据来表示存款和储蓄。编写翻译程序集或模块时,编译器会制造一个类别定义表、三个字段定义表、2个艺术定义表以及其它表。而笔者辈只要想动态调用那些元数据表,或视为为这一个元数据创设四个对象模型,那几个进度就是反光。

然而,枚举enum是1个大旨类型,它不会落到实处别的的接口,显著,不可能直接将枚举绑定到下拉框上,那么应该使用什么点子吗?

伍.用到泛型来完毕代码重用

侦查地点的代码,假如大家前天有另一个枚举,叫做TicketStatus,那么大家要将它绑定到列表,大家唯1供给转移的正是此处:

Type enumType = typeof(BookingStatus); //将BookingStatus改作TicketStatus

既然如此那样,我们何不定义二个泛型类来进展代码重用呢?大家管这些泛型类叫做EnumManager<TEnum>。

public static class EnumManager<TEnum>
{
    private static DataTable GetDataTable()
    {
       Type enumType = typeof(TEnum);  // 获取项目对象
       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 (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, 田野同志.Name);
也足以如此

              table.Rows.Add(row);
           }
       }
       return table;
    }

    public static void SetListControl(ListControl list)
    {
       list.DataSource = GetDataTable();
       list.DataTextField = “Name”;
       list.DataValueField = “Value”;
       list.DataBind();
    }
}

OK,以往整个都变得简便的多,以往,大家再要求将枚举绑定到列表,只要这么就行了(ddl起先的是DropDownList,rbl起先的是RadioButtonList):

EnumManager<BookingStauts>.SetListControl(ddlBookingStatus);
EnumManager<TicketStatus>.SetListControl(rblTicketStatus);

NOTE:借使你对泛型不熟悉,请参阅 C#
中的泛型
一文。下面的兑现并不曾思索到质量的难点,仅仅为了引出反射使用的1个实例。

第一节 加载程序集

简单的说通俗的说,正是动态调用编写翻译过的主次集中的性质,字段,方法等的进度,就是反光。

 

陆 .Net 中反射的三个范例。

甭管是VS2005的智能提示,照旧修改变量名时的重构作用,都利用了反光作用。在.Net
FCL中,也平常能来看反射的影子,那里就向大家演示多少个最广泛的例证。大家精晓,在CL兰德奔驰G级中总共有两连串型,一种是值类型,一种是引用类型。声美素佳儿个引用类型的变量并对项目实例化,会在应用程序堆(Application
Heap)上分配内部存款和储蓄器,创制对象实例,然后将指标实例的内部存款和储蓄器地址重返给变量,变量保存的是内存地址,实际也正是多个指针;声澳优个值类型的实例变量,则会将它分配在线程堆栈(Thread
Stack)上,变量本人带有了值类型的保有字段。

近日壹经我们须求比较多个目标是不是等于。当大家比较八个引用类型的变量是还是不是等于时,大家比较的是那五个变量所指向的是否堆上的同二个实例(内部存储器地址是不是壹律)。而当我们比较多个值类型变量是还是不是等于时,如何是好吗?因为变量自个儿就包蕴了值类型全数的字段(数据),所以在相比时,就供给对多少个变量的字段实行逐项的一定的可比,看看每一种字段的值是还是不是都极度,若是别的二个字段的值不等,就重回false。

实际上,执行那样的八个比较并不需求我们团结编排代码,Microsoft已经为大家提供了落成的点子:全体的值类型继承自
System.ValueType, ValueType和富有的门类都延续自System.Object
,Object提供了二个Equals()方法,用来判断五个目的是不是等于。可是ValueType覆盖了Object的Equals()方法。当大家相比五个值类型变量是不是等于时,可以调用继承自ValueType类型的Equals()方法。

public 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;
}

您有未有想到当调用Equals()方法时会爆发怎么样事吗?前边大家已经涉及假设是值类型,会对多少个变量的字段进行逐一的相比较,看看每一个字段的值是还是不是都非凡,不过怎样收获变量的兼具字段,遍历字段,并一一相比呢?此时,你应当发现到又到了用到反射的时候了,让大家利用reflector来查阅ValueType类的Equals()方法,看看微软是如何是好的啊:

public override bool Equals(object obj) {
    if (obj == null) {
       return false;
    }
    RuntimeType type = (RuntimeType)base.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.NonPublic |
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) {
威尼斯人线上娱乐,           if (obj4 != null) {
              return false;
           }
       } else if (!obj3.Equals(obj4)) {
           return false;
       }
    }
    return true;
}

专注到地点加注释的那两段代码,能够看出当对值变量实行相比时,是会动用反射来促成。反射存在着品质倒霉的题材(不仅如此,还存在着众多的装箱操作),不问可见,在值类型上调用Equals()方法开发是会十分大的。但是这一个事例只是为了印证反射的用途,笔者想已经达到规定的标准了目标。上边的代码不能一心知晓也没什么,前面会再涉及。

次第集是颇具类型的聚众,它还有八个最首要的东西正是元数据。JIT就是行使程序集的TypeRef和AssemblyRef等元数据来分明所引述的顺序集及项目,那一个元数据包罗名称、版本、语言文化和公钥标记等,JIT正是基于这么些音讯来加载三个程序集到使用程序域中。如若要协调加载四个程序集,能够调用类型Assembly的LoadXXX系列措施。

反射在.NET,通过System.Reflection命名空间中的类来促成。

运用反射遍历枚举字段

7.小结

观看此间,你应有对反射有了一个发端的定义(只怕叫反射的一个用处):反射是一种普遍的叫法,它经过
System.Reflection 命名空间 并 合作 System.Type
类,提供了在运维时(Runtime)对于 类型和对象(及其成员)的中坚新闻 以及
元数据(metadata)的造访能力。

 

(壹) Load重载系列

贰.反光能为我们做些什么?

要遍历枚举,首先就要求二个饱含枚举每一个字段新闻的靶子,这一个目的至少应该包罗四个个性,2个是字段的名目,贰个是字段的值,以有利于后续绑定。

该方法会根据一定的逐1查找钦赐目录中的程序集:先去GAC中寻找(假使是三个强命名程序集),若是找不到,则去应用程序的基目录、子目录查找。假如都没找到,则抛出尤其。如下代码加载程序集MyAssemblyB:

那些难点是我们上学反射的重点,总得知道学习它的好处,才会继续把本文看下来。

先看下完整的代码:

            string assemblyName = "MyAssemblyB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
            Assembly assembly = Assembly.Load(assemblyName);

反射个性,确实是.NET3个不胜主要且实用的风味。

        private void Form1_Load(object sender, EventArgs e)
        {
            comboBox1.DataSource = GetDataTable();
            comboBox1.DisplayMember = "Name";
            comboBox1.ValueMember = "Value";
        }

      public static DataTable GetDataTable()
        {
            Type t = typeof(BookingStatus);  //创建类型
            FieldInfo[] fieldinfo = t.GetFields(); //获取字段信息对象集合

            DataTable table = new DataTable();
            table.Columns.Add("Name", typeof(String));
            table.Columns.Add("Value", typeof(Int32));

            foreach (FieldInfo field in fieldinfo)
            {
                if (!field.IsSpecialName)
                {
                    DataRow row = table.NewRow();
                    row[0] = field.Name;   //获取文本字段
                    row[1] = (int)field.GetRawConstantValue();  //获取int数值
                    table.Rows.Add(row);
                }
            }
            return table;
        }
    }

    public enum BookingStatus
    {
        未提交 =1,
        已提交,
        已取消,
        已定妥 = 6
    }

(二) LoadFrom重载系列

A.枚举类型成员

 

加载钦命程序集名称或路径的程序集,其在里边调用Load方法,并且还能内定二个网络路径,假若钦定网络路径,则先下载该程序集,再将其加载到程序域,如下代码:

B.实例化新目的

效果:威尼斯人线上娱乐 2

Assembly.LoadFrom("http://solan.cnblogs.com/MyAssembly.dll");

C.执行对象成员

此处大概做贰个注脚:Type抽象类提供了拜访类型元数据的力量,当实例化了二个Type对象后,能够经过它的属性和艺术,获取项目标元数据的音信,只怕进一步取得该类型的成员的元数据音信。注意到此地,因为Type对象总是基于某一具体品种的,并且它是三个抽象类,所以再成立Type类型时,必要提供项目名称也许项指标实例。程序集元数据,通过Type类型就能够访问类型的元数据音信,而访问类型元数据的操作,就叫做反射。

(三) LoadFile重载体系

D.查找类型新闻

 

从随机路径加载3个程序集,并且能够从分裂途径加载相同名称的程序集。

E.查询程序集音讯

接纳泛型来达到代码重用

在1个门类中,恐怕程序集以内都有依靠关系,也得以将3个顺序集作为能源数量嵌入到多个先后集中,在急需时再加载该程序集,那时通过注册ResolveAssembly事件来加载这么些程序集。如下;

F.检查采纳于某种类型的自定义本性

着眼地点的代码,假设明天有另多个枚举,叫做TicketStatus,那么要将它的枚举项文件和值转换为DataTable,唯1必要变更的正是那里:

威尼斯人线上娱乐 3

G.创造和编写翻译新的先后集

Type t = typeof(BookingStatus); //将枚举名称更换
            AppDomain.CurrentDomain.AssemblyResolve += (sender, arg) =>
            {
                byte[] buffer = null;
                using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("ConsoleApp.MyAssemblyA.dll"))
                {
                    buffer = new byte[stream.Length];
                    stream.Read(buffer, 0, buffer.Length);
                }
                return Assembly.Load(buffer);
            };

H.简化执行时而非编写翻译时绑定的多少的操作。(C#四.0之后新职能)

既然如此这样,就能够运用泛型来兑现代码的重用,将回来DataTable的章程更改为泛型方法:

威尼斯人线上娱乐 4

其余.NET新本子中允许泛型上的反射.

     public static DataTable GetDataTable<T>()
        {
            Type t = typeof(T);  //创建类型
            FieldInfo[] fieldinfo = t.GetFields(); //获取字段信息对象集合

            //...............省略            

            return table;
        }

上述代码供给必须先将MyAssemblyA.dll文件以能源情势嵌入到ConsoleApp项目中。那样在运营ConsoleApp程序时,固然运用了MyAssemblyA中的类型且未找到MyAssemblyA.dll文件,则会跻身上边的事件措施来加载程序集MyAssemblyA。

以上是反光的基本特征,参考了《C#本质论》和《C#高级编制程序》

从以上代码能够见到,综合应用反射,泛型等技能,能够十分的大地升高代码的八面见光,可重用性。

一旦只是想理解贰个主次集的元数据解析其品种而不调用类型的分子,为了增强质量,能够调用那么些主意:

传说上边的骨干特征,大家能够布置出举不胜举丰盛实用的编制程序情势。

 

Assembly.ReflectionOnlyLoadFrom(String assemblyFile)
Assembly.ReflectionOnlyLoad(byte[] rawAssembly)
Assembly.ReflectionOnlyLoad(String assemblyName)

上边列举二种基于反射设计形式下的实例:

若是准备调用上边那多个点子加载的先后集中类型的代码,则CLR会抛出卓殊。

A.利用反射创动态成立程序集的API文书档案。基于反射允许枚举程序集中类型及成员的性状,大家得以由此反射获取已编写翻译的主次集中的字段方法属性事件和他们的XML注释。从而动态成立程序集的API文档;

 

B.非平日用的反光工厂方式。反射工厂形式在设计形式中相比较不难掌握,也比较简单。很多代码生成器中就选择那种设计格局达成分化数据库的反光调用。比如我们有MsSql、MySql、Oracle那二种数据库,在项目统一筹划中,大家有望每日换另一种数据库,因而要求同时落实那三种数据库的根底增加和删除改查的类即数据访问类。我们要切换数据库的时候,只必要在config中改变数据库类型,其余的干活付出反射工厂类去动态调用编写翻译好的次序集中对应的数据库访问方法。

第三节 反射

固然未有明了也没提到,那里只是说澳优下反光的行使实例,以便于更有信心的读书反射。反射在设计情势中的应还有不少,那里不再列举。

大家知道,在程序集(或模块)内有三个很要紧的数额就是元数据,它们描述了项目定义表,字段定义表,方法表等,也正是说全部的品种及成员定义项都会在此处被驾驭详细地记录下来。很肯定,假如我们得到了那个“描述音讯”,当然就一定于已经颇负盛名知晓了三个连串及其成员,进而就足以“构造”那个连串,通过反射就能够达到那样的指标。另人和颜悦色的是大家不用分析那多少个元数据就可以方便地取得程序集内的花色成员,.NET
Framework提供了壹部分与此相关的类定义在命名空间System.Reflection下。

三.反光应用基础

反射提供了打包程序集、模块和项目标目的(Type
类型)。反射机制运作在程序运维时动态发现项目及其成员。

地方说了这般多,无非正是先让我们掌握反射能为大家做些什么,上面进入正题,说一下反光的代码达成。

(1)查找程序集内所定义的类别

上面主要介绍反射的大旨类及类成员

在将某一程序集加载到使用程序域后,能够因而Assembly的GetExportedTypes方法来取得该程序集全体的公开类型,如下代码:

反射的命名空间:System.Reflection

威尼斯人线上娱乐 5

反射的类大多都在那么些命名空间中。

        private void GetTypes()
        {
            string assemblyName = "MyAssemblyB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
            Assembly assembly = Assembly.Load(assemblyName);
            Type[] types = assembly.GetExportedTypes();
            foreach (Type t in types)
            {
                Console.WriteLine(t.Name);
            }
        }

关键的类:System.Type

威尼斯人线上娱乐 6

以此类是反射的大旨,其质量方法能够博得周转时的音讯。

(贰)查找类型成员

Type类派生于System.Reflection.MemberInfo抽象类

在命名空间System.Reflection中有多个虚无类型MemberInfo,它包裹了与类型成员相关的通用属性,每1个档次成员都有八个相应的从MemberInfo派生而来的门类,并且放置了部分非正规的性质特征,如FieldInfo、MethodBase(ContructorInfo、MethodInfo)、PropertyInfo和伊芙ntInfo。能够透过调用类型Type对象的GetMembers方法赢得该项指标持有成员或相应成员,如下代码(对地点的GetTypes方法的改动)获取全体分子列表:

MemberInfo类中的只读属性

            Type[] types = assembly.GetExportedTypes();
            foreach (Type t in types)
            {
                Console.WriteLine(t.Name);
                MemberInfo[] members = t.GetMembers();
            }

属性

Type有一组GetXXX方法是获取对象成员的,以下列出部分艺术:

描述

GetConstructor/GetConstructors //获取构造函数
GetEvent/GetEvents //获取事件
GetField/GetFields //获取字段
GetMethod/GetMethods //获取方法
GetProperty/GetProperties //获取属性

备注

还要每一个方法都足以选拔1个枚举类型BindingFlags的参数钦定控制绑定和由反射执行的成员和类别搜索方法的标志。有关BindingFlags
枚举可参考MSDN文档.aspx%E3%80%82)

TypeDeclaringType

1般来说代码获取奥迪(Audi)Car类型的Owner属性和Run()方法:

获取注明该成员的类或接口的品类

威尼斯人线上娱乐 7

MemberTypesMemberType

        private void GetTypeMethod()
        {
            string assemblyName = "MyAssemblyB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
            Assembly assembly = Assembly.Load(assemblyName);
            Type t = assembly.GetType("MyAssemblyB.AudiCar");
            MethodInfo method = t.GetMethod("Run");
            PropertyInfo pro = t.GetProperty("Owner");
        }

获得成员的项目,那个值用于提醒该成员是字段、方法、属性、事件、或构造函数

威尼斯人线上娱乐 8

那是三个枚举,它定义了用来表示区别成员的类型值。这几个值包涵:MemberTypes.Constructor,MemberTypes.Method,MemberTypes.Field,MemberTypes.伊芙nt,MemberTypes.Property。由此得以由此检查MemberType属性来规定成员的门类,例如,在MemberType属性的值为MemberTypes.Method时,该成员为格局

(三)构造类型实例

IntMetadataToken

在获得花色及成员音信之后,我们就能够构造类型的实例对象了。FCL提供了多少个主意来布局七个品种的实例对象,有关那几个方法详细内容,可参看MSDN文书档案:

收获与特定元数据相关的值

Activator.CreateInstance() //重载系列
Activator.CreateInstanceFrom() //重载系列
AppDomain.CurrentDomain.CreateInstance() //重载系列
AppDomain.CurrentDomain.CreateInstanceFrom() //重载系列

ModuleModule

正如构造奥迪(Audi)Car类型的实例:

获取三个代表反射类型所在模块的Module对象

威尼斯人线上娱乐 9

StringName

        private void TestCreateInstance()
        {
            string assemblyName = "MyAssemblyB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
            Assembly assembly = Assembly.Load(assemblyName);
            Type t = assembly.GetType("MyAssemblyB.AudiCar");
            var obj = Activator.CreateInstance(t);
            Debug.Assert(obj != null);
        }

成员的名目

威尼斯人线上娱乐 10

TypeReflectedType

看一下调节和测试:

反射的指标类型

威尼斯人线上娱乐 11

Type类的只读属性

其余,还是能够调用类型的构造函数创制实例对象,如下:

属性

obj = t.InvokeMember("AudiCar", BindingFlags.CreateInstance, null, null, null);

描述

 

AssemblyAssembly

第5节 通过反射访问对象成员

获得钦命项目标次第集

设若单纯获得类型的靶子,好像意义并相当的小,大家更加多的是要操作对象,比如访问属性,调用方法等,这一节大家来看一下怎么访问成员。

TypeAttributesAttributes

项目Type提供了多个造访指标项目成员的要命可靠的章程InvokeMember,调用此办法时,它会在项目成员中找到对象成员(这一般钦点成员名称,也能够内定搜索筛选标准BindingFlags,假使调用的目的成员是措施,还是可以给艺术传递参数。),借使找到则调用目的措施,并赶回指标访问归来的结果,假诺未找到,则抛出十二分,假诺是在目的措施内部有11分,则InvokeMember会先捕获该越发,包装后再抛出新的不胜TargetInvocationException。以下是InvokeMember方法的原型:

收获制定项指标特色

威尼斯人线上娱乐 12

TypeBaseType

public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args);
public object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target, object[] args,
 CultureInfo culture);
public abstract object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object target,
 object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters);
name 目标方法名称
invokeAttr 查找成员筛选器
binder 规定了匹配成员和实参的规则
target 要调用其成员的对象
args 传递给目标方法的参数

获得钦赐项目标直接基类型

威尼斯人线上娱乐 13

StringFullName

在上1节的末段大家来得了何等调用类型的构造函数来实例化一个指标,上边包车型大巴代码演示了什么调用对象的章程,个中措施Turn接收三个Direction类型的参数:

收获钦点项目标全名

            string assemblyName = "MyAssemblyB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
            Assembly assembly = Assembly.Load(assemblyName);
            Type t = assembly.GetType("MyAssemblyB.AudiCar");
            var obj = Activator.CreateInstance(t);
            t.InvokeMember("Turn", BindingFlags.InvokeMethod, null, obj, new object[] { Direction.East });

boolIsAbstract

其余,调用目的对象的法子,还能以MethodInfo的办法进行,如下:

万一钦定项目是空虚类型,重返true

            Type t = assembly.GetType("MyAssemblyB.AudiCar");
            var obj = Activator.CreateInstance(t);
            MethodInfo method = t.GetMethod("Turn");
            method.Invoke(obj, new object[] { Direction.Weast });

boolIsClass

以下是对质量的读写操作:

只要钦定项目是类,重返true

            Type t = assembly.GetType("MyAssemblyB.AudiCar");
            var obj = Activator.CreateInstance(t);
            //为属性Owner赋值
            obj.GetType().GetProperty("Owner").SetValue(obj, "张三", null);
            //读取属性Owner的值
            string name = (string)obj.GetType().GetProperty("Owner").GetValue(obj, null);

stringNamespace

对于别的成员(如字段等)的拜会,可参照MSDN文书档案。

赢得钦赐项目标命名空间

反射对泛型的支撑

Type类的措施

如上的示范都是对准普通品种,其实反射也提供了对泛型的支撑,那里只不难演示一下反光对泛型的差不离操作。比如大家有如下3个泛型类型定义:

方法

威尼斯人线上娱乐 14

描述

namespace MyAssemblyB
{
    public class MyGeneric<T>
    {
        public string GetName<T>(T name)
        {
            return "Generic Name:" + name.ToString();
        }
    }
}

ConstructorInfo[]GetConstructors()

威尼斯人线上娱乐 15

获取钦赐项指标构造函数列表

其1类型不会细小略,类型MyGeneric内有一个主意,该措施重返带有附加新闻”
Generic Name:”的称号。先来看一下如何获取钦命参数类型为string的泛型类:

EventInfo[]GetEvents();

威尼斯人线上娱乐 16

获得钦点项指标光阴列

        private void TestGenericType()
        {
            string assemblyName = "MyAssemblyB, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
            Assembly assembly = Assembly.Load(assemblyName);
            Type[] types = assembly.GetExportedTypes();
            foreach (Type t in types)
            {
                //检测是否泛型(在程序集MyAssemblyB中只定义了一个泛型类型 MyGeneric<T>)
                if (t.IsGenericType)
                {
                    //为泛型类型参数指定System.String类型,并创建实例
                    object obj = Activator.CreateInstance(t.MakeGenericType(new Type[] { typeof(System.String) }));
                    //生成泛型方法
                    MethodInfo m = obj.GetType().GetMethod("GetName").MakeGenericMethod(new Type[] { typeof(System.String) });
                    //调用泛型方法
                    var value = m.Invoke(obj, new object[] { "a" });
                    Console.WriteLine(value);
                }
            }
        }

FieldInfo[]GetFields();

威尼斯人线上娱乐 17

赢得钦定项指标字段列

调节起来,看一下末尾的value值:

Type[]GetGenericArguments();

威尼斯人线上娱乐 18

赢得与已结构的泛型类型绑定的花色参数列表,如果内定项指标泛型类型定义,则得到类型形参。对彭三源早布局的种类,该列表就大概同时富含类型实参和类型形

反射泛型的时候,要先鲜明目的项目是泛型,在开立泛型类型实例前,必须调用MakeGenericType方法协会3个着实的泛型,该措施接收贰个要钦点泛型类型参数的种类数组,同样调用泛型方法前要调用方法MakeGenericMethod构造相应的泛型方法,此办法也吸收一个点名泛型类型的类型数组。

MethodInfo[]GetMethods();

 

赢得钦定项指标措施列表

第陆节 动态创制类型

PropertyInfo[]GetProperties();

近日几节所讲述的都以依照已经存在程序集的气象下展开反射,.NET
Framework还提供了在内存中动态成立类型的强大功效。大家领会程序集蕴涵模块,模块包涵项目,类型包罗成员,在动态创制类型的时候也是要遵照这些顺序。动态成立类型是依照元数据的达成情势来落到实处的,这壹局地被定义在命名空间System.Reflection.Emit内,有一文山会海的XXXBuilder构造器来创建相应的品种对象。大家来看1要动态成立类型,有怎么着步骤(那里只是简单演示):

赢得钦赐项指标属性列表e

(一) 程序集是老窝,所以要先创建3个顺序集:

MemberInfo[]GetMembers();

AssemblyBuilder aBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("TempDynamicAssembly"), AssemblyBuilderAccess.Run);

赢得钦点项目标成员列表

(二) 有了程序集,接下去是模块

反射还有众多类,那里不一一介绍,详细可以查看MSDN:

ModuleBuilder mBuilder = aBuilder.DefineDynamicModule("NotifyPropertyChangedObject");

(三) 接下来正是成立项目了:

4.反射实例

this.tBuilder = mBuilder.DefineType(typeFullName, TypeAttributes.Public | TypeAttributes.BeforeFieldInit);

下边通过3个实例来学习一下反光最大旨的应用方式。

(四)
以后能够创立项指标积极分子了,为项目创设二个个性Name。大家领会属性包蕴字段和对字段的四个访问器,所以应该先创立字段,然后再创建五个访问器方法,那壹段是鲁人持竿IL码的先后顺序来的,如下:

建立一个化解方案,蕴含多少个品种,项目ClassLibrary生成二个DLL,另八个档次是ReflectionTestGet,用于反射调用类ClassLibrary

威尼斯人线上娱乐 19

威尼斯人线上娱乐 20

            FieldBuilder fieldBuilder = this.tBuilder.DefineField(string.Format("{0}Field", propertyName), propertyType, FieldAttributes.Private);
            PropertyBuilder propertyBuilder = tBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
            MethodBuilder getAccessor = tBuilder.DefineMethod(string.Format("get_{0}", propertyName), getSetAttr, propertyType, Type.EmptyTypes);
            ILGenerator getIL = getAccessor.GetILGenerator();
            getIL.Emit(OpCodes.Ldarg_0);
            getIL.Emit(OpCodes.Ldfld, fieldBuilder);
            getIL.Emit(OpCodes.Ret);
            propertyBuilder.SetGetMethod(getAccessor);

            MethodBuilder setAccessor = tBuilder.DefineMethod(string.Format("set_{0}", propertyName), getSetAttr, null, new Type[] { propertyType });
            setAccessor.DefineParameter(1, ParameterAttributes.None, "value");
            ILGenerator setIL = setAccessor.GetILGenerator();
            setIL.Emit(OpCodes.Nop);
            setIL.Emit(OpCodes.Ldarg_0);
            setIL.Emit(OpCodes.Ldarg_1);
            setIL.Emit(OpCodes.Stfld, fieldBuilder);
            setIL.Emit(OpCodes.Ldarg_0);
            setIL.Emit(OpCodes.Ldstr, propertyName);
            setIL.Emit(OpCodes.Call, this.mBuilder);
            setIL.Emit(OpCodes.Nop);
            setIL.Emit(OpCodes.Ret);
            propertyBuilder.SetSetMethod(setAccessor);

首先个门类的七个类如下:

威尼斯人线上娱乐 21

MartialArtsMaster.cs

注意,那中间有对事件的操作,能够忽略。

威尼斯人线上娱乐 22威尼斯人线上娱乐 23

(伍) 最终调用类型构造器的CreateType()方法就能够创立该类型了:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace ClassLibrary{    /// <summary>    /// 类:武林高手    /// MartialArtsMaster    /// </summary>    class MartialArtsMaster    {        /// <summary>        /// 级别        /// </summary>        public int _level = 9;        /// <summary>        /// 编号        /// </summary>        public int Id { get; set; }        /// <summary>        /// 姓名        /// </summary>        public string Name { get; set; }        /// <summary>        /// 年龄        /// </summary>        public int Age { get; set; }        /// <summary>        /// 门派        /// </summary>        public string Menpai { get; set; }        /// <summary>        /// 武学        /// </summary>        public string Kungfu { get; set; }        /// <summary>        /// 级别        /// </summary>        public int Level        {            get            {                return _level;            }            set            {                _level = value;            }        }        /// <summary>        /// 攻击        /// </summary>        /// <param name="kungfu"></param>        /// <returns></returns>        public string Attack(string kungfu)        {            return "使用用了功夫:" + kungfu;        }        public string Kill(string kungfu, string name)        {            return "使用用了功夫:" + kungfu + "击杀了" + name;        }    }}
tBuilder.CreateType();

View Code

该形式再次回到三个Type类型。

Person.cs

花色创设完毕后,我们就能够利用上一节讲的反光相关文化对该项目实行操作了,那里当然是四个简短的品类,借使想创建复杂的类型,比如有艺术,事件等成员,那可以发布您的汇编能力来日趋折腾啊,也足以体会一下立刻汇编制程序序员们的苦逼!托管下的汇编编码已经很简化了,围绕Emit方法折腾死!如果想研讨IL,能够用IL
DASM打开托管程序集,慢慢欣赏吧。

威尼斯人线上娱乐 24威尼斯人线上娱乐 25

在大家的数见不鲜开销中,有时用了动态类型可能很有利的,比如当你要开创贰个DataGrid的数目源DataTable,但某些列不明显,列的数据类型不分明,列名也不鲜明的情形下,那时根据须求创造3个动态类型,继而再次创下制3个该项目标聚合就很方便使用了。笔者封装了七个动态创造类型的类,在本文的结尾提供下载,喜欢的能够拿去。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace ClassLibrary{    /// <summary>    /// 类:人    /// </summary>    class Person    {        public string gender { get; set; }        public string race { get; set; }        public string Country { get; set; }        public string Eat(string strCountry)        {            switch (strCountry)            {                case "美国":                    return "爱吃西餐";                case "韩国":                    return "爱吃泡菜";                default:                    return "不知道";            }        }    }}

此处所描述的是动态地在内部存款和储蓄器创制贰个类,关于动态类型dynamic和var,那里就不再瞎掰了,感兴趣的能够去寻找有关资料。

View Code

 

第叁个项目调用如下:

第陆节 应用反射时要小心的几点

威尼斯人线上娱乐 26威尼斯人线上娱乐 27

反射为大家付出提供了尤其便利的编制程序实践,但运用它也有几点须要注意。

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Reflection;namespace ReflectionTestGet{    class Program    {        static void Main(string[] args)        {            Assembly asm = Assembly.LoadFrom("ClassLibrary.dll");  //加载指定的程序集            Type[] alltype = asm.GetTypes();  //获取程序集中的所有类型列表            foreach (Type calssName in alltype)            {                Console.WriteLine("加载程序的集类名:"+ calssName.Name);  //打印出程序集所有类                foreach (var field in calssName.GetFields                    Console.WriteLine(calssName.Name+"字段有:" + field.Name);  //打印出程序集所有字段,注意只能获取公有字段                foreach (var pro in calssName.GetProperties                    Console.WriteLine(calssName.Name + "属性有:" + pro.Name);  //打印出程序集所有属性                foreach (var met in calssName.GetMethods                    Console.WriteLine(calssName.Name + "方法有:" + met.Name);  //打印出程序集所有方法            }            Console.ReadKey();        }    }}

既然是反射,大家在编码时对项目是未知的,要是是已知,就没须要再用反射了,
除非是要做类似分析类型元数据的工具,而笔者辈1般采纳反射是要操作其属性字段、调用其艺术等,目标是用而不是分析。在编写翻译使用了反光的代码进程中,反射的对象项目是不安全的,很有不小大概在调用反射出来的类对象时出错,那点要留意。

View Code

反射是基于元数据实现的,所以在运用反射进度中,代码会寻找程序集的元数据,那几个元数据是遵照字符串的,并且不可能预编写翻译,所以那一多元的操作对品质有人命关天影响。别的,由于大家对指标项目未知,在向方法传递参数时常常是以object数组传递,CL卡宴会每一个检查参数的数据类型,无论是传入仍旧回到,都有一点都不小可能率开展大气的类型转换,这也有毒了质量。所以对于反射的运用,应该注意。当然,像有个别O科雷傲M等框架是以捐躯质量来换取方便的开销体验就另当别说了。

运行结果如下:

 

威尼斯人线上娱乐 28

转自:

伍.本节中央:

本节重大介绍和反光的用处及反光的骨干操作类及质量方法,下节三番五次深切介绍怎么着将反射技术利用于实际项目里面。

==============================================================================================

归来目录

<借使对您有救助,记得点一下推荐哦,如有

**有不明白或不当之处,请多调换>**

<对本类别作品阅读有难堪的情侣,请先看《.net面向对象编制程序基础》>

<转发申明:技术必要共享精神,欢迎转发本博客中的小说,但请注解版权及U悍马H二L>

.NET
技术交换群:46718953三

威尼斯人线上娱乐 29

==============================================================================================


相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图