前言

自笔者驾驭:

反射

反射

编制程序其实正是写代码,而写代码指标正是兑现业务,所以,语法和框架也是为着贯彻工作而存在的。由此,不管多么巨大上的对象,实质上都是工作。

装配件:Assembly(程序集)

简介

  反射是
.NET中的首要机制,通过反射,能够在运转时获得程序或程序集中类型(包涵class、struct、delegate、interface 和 enum 等)的积极分子和成员的新闻。

  通过反射,即可对每一种档次了如指掌,并且也足以透过反射成立、调用和做客对象,即便在编写翻译时不分明该目的的连串。

  程序集带有模块,模块包蕴类型,而项目涵盖成员。反射提供包装程序集、模块和档次的靶子。能够选用反射动态地成立项指标实例,将项目绑定到存活对象,或从现有对象中获得项目。

简介

  反射是
.NET中的主要体制,通过反射,能够在运转时收获程序或程序集中类型(包罗class、struct、delegate、interface 和 enum 等)的成员和分子的音讯。

  通过反射,即可对每1种档次了如指掌,并且也能够因此反射创设、调用和走访对象,就算在编写翻译时不明确该指标的档次。 

  程序集带有模块,模块包蕴类型,而项目涵盖成员。反射提供包装程序集、模块和花色的指标。能够应用反射动态地创立项目标实例,将项目绑定到现有对象,或从现有对象中取得项目。

 

之所以,我认为毫无把写代码回涨到科学的冲天。上涨到艺术就足以了,因为艺术自己也远非惊人。。。。

金沙注册送58,晚绑定:后期绑定

优缺点

  优点:

  1. 拉长了程序的一帆风顺和扩大性;
  2. 降低耦合性;
  3. 它同意程序创立和决定别的类的对象,无需提前硬编码目的类。

  缺点:

  1. 性情:使用反射基本上是一种解释操作,从理论上讲使用反射远慢于间接代码;
  2. 可读性下落。

优缺点

  优点:

  1. 进步了先后的八面玲珑和扩充性;
  2. 下降耦合性;
  3. 它同意程序创造和操纵其余类的靶子,无需提前硬编码指标类。

  缺点:

  1. 天性:使用反射基本上是一种解释操作,从理论上讲使用反射远慢于直接代码;
  2. 可读性下跌。

 

软件设计存在过度设计,语法和框架的精通,也存在过度精通。比如,反编写翻译下,看看反射是怎么落实的。。。

MSDN:反射(C#
编制程序指南).aspx)

反射的门类成员消息

  • Assembly:定义和加载程序集。

  • Module:模块音讯(如含有模块的程序集和模块中的类)。

  • ConstructorInfo:构造函数音讯(如名称、参数、访问修饰符等)。
  • MethodInfo:方法成员新闻(如名称、重返类型、参数和做客修饰符等)。

  • FieldInfo:字段成员新闻(如名称、访问修饰符)。

  • 伊芙ntInfo:事件成员消息(如名称、事件处理程序的数据类型、自定义天性、表明类型以及事件的反光的档次)。

  • PropertyInfo:属性成员音讯(如名称、数据类型、注脚类型,反射的类型和天性的只读或可写状态),并拿走或安装属性值。

  • ParameterInfo:参数成员音信(如参数名、数据类型以及参数在章程签名中的地方等)。

  • CustomAttributeData:自定义本性音信。

  System.Reflection.Emit命名空间的类提供一种专用情势的反射,使您可见在运转时生成类型。

架构师的入门基础。反射的种类成员消息

  • Assembly:定义和加载程序集。

  • Module:模块消息(如带有模块的程序集和模块中的类)。 

  • ConstructorInfo:构造函数消息(如名称、参数、访问修饰符等)。
  • MethodInfo:方法成员新闻(如名称、再次来到类型、参数和访问修饰符等)。

  • FieldInfo:字段成员信息(如名称、访问修饰符)。

  • 伊夫ntInfo:事件成员音讯(如名称、事件处理程序的数据类型、自定义个性、注脚类型以及事件的反射的品种)。

  • PropertyInfo:属性成员音讯(如名称、数据类型、申明类型,反射的种类和总体性的只读或可写状态),并取得或设置属性值。

  • ParameterInfo:参数成员新闻(如参数名、数据类型以及参数在格局签名中的地方等)。

  • CustomAttributeData:自定义天性音信。

 

  System.Reflection.Emit 命名空间的类提供1种专用情势的反光,使您可见在运作时生成类型。

 

有趣味是好事,但固然知道了反光的精神,了然了反光是如何规划的,你技术也没怎么质的转移。因为,技术水平末了照旧要落到实处到应用上。

—————–原作如下——–

反射的大致用法

  命名空间:System.Reflection、System.Type、System.Reflection.Assembly

  常见的得到 Type 对象的用法:

            Type type1 = typeof(string);            string msg = "";            Type type2 = msg.GetType();

反射的粗略用法

  命名空间:System.Reflection、System.Type、System.Reflection.Assembly

  常见的获得 Type
对象的用法:

            Type type1 = typeof(string);
            string msg = "";
            Type type2 = msg.GetType();

 

 

在比如,过度的求偶代码品质,也不见得是一件好事,因为,[大多数]气象下,硬件比程序员便宜多了。。。(注意那里指的是代码不是算法和数据库品质)

一、
什么是反光
2、
命名空间与装配件的涉嫌
三、
运营期获得类型音信有怎么着用
四、
怎样运用反射获取项目
五、
怎么样依据项目来动态创立对象
6、
如何取得方式以及动态调用方法
七、
动态成立委托

三个常见的示范用法

  咱们①开端读书三层架构的时候,都应当会友善接着导师入手塑造三个SqlHelper
的啊,那里作者截取一个通过反射读取数据库数据并填充到3个目的的性质上,通过巡回遍历,最后生成多个list 列表的代码。

        /// <summary>        /// 执行 Reader 并读取数据转换成集合        /// </summary>        /// <typeparam name="T"></typeparam>        /// <param name="sql"></param>        /// <param name="commandType"></param>        /// <param name="parameters"></param>        /// <returns></returns>        public static IList<T> ExecuteReaderToList<T>(string sql, CommandType commandType = CommandType.Text,            params SqlParameter[] parameters) where T : new()        {            var type = typeof;            var props = type.GetProperties();            var list = new List<T>();            using (var reader = ExecuteDataReader(sql, commandType, parameters))            {                while (reader.Read                {                    var entity = new T();                    foreach (var propertyInfo in props)                    {                        var schemaTable = reader.GetSchemaTable();                        if (schemaTable == null)                            return new List<T>();                        schemaTable.DefaultView.RowFilter = $"ColumnName='{propertyInfo.Name}'";                        if (schemaTable.DefaultView.Count <= 0) continue;                        if (!propertyInfo.CanWrite)                            continue;                        var val = reader[propertyInfo.Name];                        if (val != DBNull.Value)                            propertyInfo.SetValue(entity, val);                    }                    list.Add;                }            }            return list;        }

  简单分析应用反射的代码:

    type.GetProperties():获取属性集合;

    propertyInfo.CanWrite:可写属性;

    propertyInfo.SetValue(entity,
val):属性赋值,选取相应的指标实行赋值。


反骨仔

微软官方文档

 2个普遍的示范用法

  大家1初始学习3层架构的时候,都应当会融洽接着导师入手制作三个SqlHelper
的吧,那里自身截取2个因此反射读取数据库数据并填充到八个指标的个性上,通过轮回遍历,最后生成八个list 列表的代码。

        /// <summary>
        /// 执行 Reader 并读取数据转换成集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="commandType"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public static IList<T> ExecuteReaderToList<T>(string sql, CommandType commandType = CommandType.Text,
            params SqlParameter[] parameters) where T : new()
        {
            var type = typeof(T);
            var props = type.GetProperties();
            var list = new List<T>();

            using (var reader = ExecuteDataReader(sql, commandType, parameters))
            {
                while (reader.Read())
                {
                    var entity = new T();

                    foreach (var propertyInfo in props)
                    {
                        var schemaTable = reader.GetSchemaTable();
                        if (schemaTable == null)
                            return new List<T>();

                        schemaTable.DefaultView.RowFilter = $"ColumnName='{propertyInfo.Name}'";
                        if (schemaTable.DefaultView.Count <= 0) continue;

                        if (!propertyInfo.CanWrite)
                            continue;

                        var val = reader[propertyInfo.Name];

                        if (val != DBNull.Value)
                            propertyInfo.SetValue(entity, val);
                    }

                    list.Add(entity);
                }
            }

            return list;
        }

  不难分析应用反射的代码:

    (一)type.GetProperties():获取属性集合;

    (二)propertyInfo.CanWrite:可写属性;

    (3)propertyInfo.SetValue(entity,
val):属性赋值,采取相应的靶子开始展览赋值。

 

 


【博主】反骨仔

【原文】 

【参考】微软官方文书档案

 

于是,不论什么事,过度了,总不是好事。

一、什么是反光
 
      Reflection,粤语翻译为反射。
 
     
那是.Net中取得运转时类型音信的章程,.Net的应用程序由多少个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编制程序的不2法门,让程序员能够在先后运维期得到这多少个组成都部队分的连锁音讯,例如:


 
     
Assembly类能够获得正在运作的装配件新闻,也能够动态的加载装配件,以及在装配件中找寻类型消息,并创设该项目标实例。
Type类能够取得对象的类型消息,此音信包罗对象的保有因素:方法、构造器、属性等等,通过Type类能够获得这个成分的消息,并且调用之。
MethodInfo包罗方法的新闻,通过那几个类能够拿走方法的名号、参数、再次回到值等,并且可以调用之。
那般,还有FieldInfo、伊夫ntInfo等等,那一个类都包涵在System.Reflection命名空间下。

本篇小说主要介绍C#反射【用法】。

二、命名空间与装配件的关联
 
     
很四人对那些定义恐怕照旧很不明晰,对于合格的.Net程序员,有要求对这一点开始展览驳斥蜚语。
 
      命名空间类似与Java的包,但又不完全等同,因为Java的包必须依据目录结构来放置,命名空间则不须求。

反射是架设师必会的底蕴,因为别的二个被设计出来的框架,都要动用反射。

 
     
装配件是.Net应用程序执行的纤维单位,编写翻译出来的.dll、.exe都以装配件。

反射也是最隐蔽的语法,因为反射写出来后,平日它会被一向封装,然后调用者就只承担利用,不再关怀她的切实可行落到实处。

 
     
装配件和命名空间的关联不是各样对应,也不互相包涵,叁个装配件里面能够有多少个命名空间,二个命名空间也得以在多个装配件中留存,那样说只怕有点模糊,举个例证:
装配件A:

这与它的特色有关,因为反射就是为着削减代码冗余而存在的,所以,看不见很正规。

  1. namespace  N1
  2. {
  3.       public  class  AC1  {…}
  4.       public  class  AC2  {…}
  5. }
  6. namespace  N2
  7. {
  8.       public  class  AC3  {…}
  9.       public  class  AC4{…}
  10. }

反射的概念

复制代码

合法概念:反射提供了包装程序集、模块和档次的目的(Type 类型)。可以选取反射动态成立类型的实例,将项目绑定到存活对象,或从现有对象获得项目并调用其艺术或访问其字段和本性。即使代码中选拔了质量,能够选用反射对它们举行访问。

装配件B:

看不懂?不要紧,大家把它翻译成人类可领略的语言。

  1. namespace  N1
  2. {
  3.       public  class  BC1  {…}
  4.       public  class  BC2  {…}
  5. }
  6. namespace  N2
  7. {
  8.       public  class  BC3  {…}
  9.       public  class  BC4{…}
  10. }

C#编制程序语言中,最常使用的是类和类中的函数和属性。正向调用的主意是,创立类,然后用类创设一个对象。接下来就能够用那么些目的调用类中的方法和总体性了。

复制代码

而反射,便是相持于这种正向调用的留存。即,它是反向调用。

那多少个装配件中都有N1和N贰四个命名空间,而且各申明了多少个类,那样是截然能够的,然后大家在3个应用程序中援引装配件A,那么在这些应用程序中,大家能见到N1上边包车型客车类为AC一和AC二,N二上边的类为AC三和AC四。
 
     
接着大家去掉对A的引用,加上对B的引用,那么大家在那些应用程序下能看到的N一下边包车型地铁类成为了BC1和BC贰,N二上边也1如既往。
 
     
要是大家还要引述那八个装配件,那么N一下边我们就能观看多少个类:AC一、AC二、BC壹和BC二。

反射能够由此类名的字符串来成立类,能够通过函数名的字符串和属性名的字符串,来调用类下的函数和属性。

 
     
到此处,大家可以清楚3个定义了,命名空间只是说美赞臣个品类是那贰个族的,比如有人是苗族、有人是柯尔克孜族;而装配件表美素佳儿(Friso)个类型住在哪个地方,比如有人住在东京、有人住在法国首都;那么上海有毛南族人,也有拉祜族人,新加坡有鄂伦春族人,也有塔塔尔族人,那是不争论的。

有同学会问了, 既然正向能够调用,那么反向调用干什么呢?

 
     
上边大家说了,装配件是贰个连串居住的地点,那么在2个先后中要运用二个类,就无法不告诉编写翻译器这一个类住在何地,编写翻译器才能找到它,也正是说必须引用该装配件。
 
     
那么只要在编写程序的时候,可能不明确这一个类在哪个地方,仅仅只是知道它的名目,就无法动用了呢?答案是能够,那便是反射了,正是在程序运转的时候提供该类型的地址,而去找到它。
有趣味的话,接着往下看吗。

会有那种问题的同窗,先别着急,继续往下看,反射既然存在,就决然有存在的道理。

3、运转期获得类型音信有哪些用
 
     
有人也许难题,既然在开发时就能够写好代码,干嘛还放置运营期去做,不光繁琐,而且功效也受影响。
那就是个不等的标题了,就跟早绑定和晚绑定一样,应用到分歧的场所。有的人反对晚绑定,理由是消耗效能,可是不少人在享用虚函数带来的益处的时侯还尚未察觉到她早已用上了晚绑定。那么些题材说开去,不是三言两语能讲精通的,所以就点到告竣了。
 
     
笔者的理念是,晚绑定能够带来许多统一筹划上的方便人民群众,合适的运用能够大大提升程序的复用性和灵活性,不过别的事物都有两面性,使用的时侯,必要再三度量。

反射的根基运用

随即说,运维期获得类型音讯到底有怎样用呢?
还是举个例子来验证,很多软件开发者喜欢在大团结的软件中留给一些接口,其余人能够编写一些插件来扩张软件的作用,比如笔者有3个媒体播放器,小编梦想现在能够很便宜的扩充识别的格式,那么作者声雅培个接口:

1,类反射

  1. public  interface  IMediaFormat
  2. {
  3. string  Extension  {get;}
  4. Decoder  GetDecoder();
  5. }

先看下边代码;代码为经过类名称的字符,反射出类的靶子。

复制代码

public class ReflectionSyntax
{ 
    public static void Excute()
    {
        Type type = GetType("Syntax.Kiba");
        Kiba kiba = (Kiba)Activator.CreateInstance(type);
        Type type2 = GetType2("Syntax.Kiba");
        Kiba kiba2 = (Kiba)Activator.CreateInstance(type2);
    }
    public static Type GetType(string fullName)
    {
        Assembly assembly = Assembly.Load("Syntax");
        Type type = assembly.GetType(fullName, true, false);
        return type;
    }

    public static Type GetType2(string fullName)
    {
        Type t = Type.GetType(fullName);
        return t;
    } 
} 
public class Kiba
{ 
    public void PrintName()
    {
        Console.WriteLine("Kiba518");
    } 
} 

那几个接口中包含1个Extension属性,那么些个性重回协助的扩大名,另3个办法再次回到2个解码器的靶子(那里自身一旦了三个Decoder的类,这几个类提供把公文流解码的功力,扩大插件可以派生之),通过解码器对象自笔者就足以表明文件流。
那么自个儿明显具有的解码插件都无法不派生多少个解码器,并且达成这么些接口,在GetDecoder方法中回到解码器对象,并且将其体系的名目配置到自家的布局文件之中。
那样的话,作者就不须求在付出播放器的时侯知道今后扩大的格式的项目,只须要从配置文件中拿走今后有所解码器的品种名称,而动态的始建媒体格式的指标,将其更换为IMediaFormat接口来采纳。

在代码中大家看来,反射时传递了字符串”Syntax.Kiba”,然后经过分析字符串,获取到了该字符串对应的类的品种,最终再借助Activator来帮衬创立类的实例。

那正是一个反光的典型应用。

其间字符串”Syntax.Kiba”是二个通通限定名。什么是一点壹滴限定名?完全限定名就是命名空间+类名。在反射的时候,需求大家传递完全限定名来分明终归要去哪个命名空间,找哪位类。

四、如何使用反射获取项目
 
      首先我们来看什么得到类型音信。
 
      获得类型音讯有三种方法,1种是收获实例对象
 
     
那几个时侯作者只是是收获这一个实例对象,得到的办法大概是2个object的引用,大概是3个接口的引用,可是本身并不知道它的适龄品种,作者急需领悟,那么就足以因而调用System.Object上注脚的章程GetType来取得实例对象的门类对象,比如在有些方法内,笔者急需看清传递进入的参数是不是完成了某些接口,借使实现了,则调用该接口的二个主意:

在代码中大家还足以看出,获取项目标诀要有两种,一种是较复杂的,壹种是回顾的。

  1. public  void  Process(  object  processObj  )
  2. {
  3. Type  t  =  processsObj.GetType();
  4. if(  t.GetInterface(“ITest”)  !=null  )
  5.                     …
  6. }

GetType二方法是简约的获得项目,通过Type间接就解析了字符串。而GetType则先举办了加载Assembly(组件),然后再由组件获取项目。

复制代码

两头有怎么着界别吧?

其余1种得到项目标不二诀倘诺经过Type.GetType以及Assembly.GetType方法,如:
 
            Type  t  =  Type.GetType(“System.String”);
 
     
供给留意的是,前边大家讲到了命名空间和装配件的关系,要物色三个类,必须钦赐它所在的装配件,可能在已经取得的Assembly实例下边调用GetType。
 
     
本装配件中项目能够只写类型名称,另3个不等是mscorlib.dll,这么些装配件中宣示的花色也足以大致装配件名称(.Net装配件编写翻译的时候,暗中同意都引用了mscorlib.dll,除非在编写翻译的时候肯定内定不引用它),比如:
 
        System.String是在mscorlib.dll中声称的,上边的Type  t  = 
Type.GetType(“System.String”)是天经地义的
 
       
System.Data.DataTable是在System.Data.dll中证明的,那么:
Type.GetType(“System.Data.DataTable”)就只好得到空引用。
 
        必须:
Type 
t  = 
Type.GetType(“System.Data.DataTable,System.Data,Version=1.0.3300.0, 
Culture=neutral,  PublicKeyToken=b77a5c561934e089”);
 
        那样才得以,大家能够看上边这么些帖子:
 
              http://expert.csdn.net/Expert/to

2.xml?temp=.1919977
 
        qqchen的答疑很精美

区分是,用Type直接解析,只可以解析当前定名空间下的类。借使此类存在于引用的DLL中,就解析不了。

五、如何依据项目来动态创立对象
 
     
System.Activator提供了主意来依据项目动态创设对象,比如创造三个DataTable:

而GetType方法中的[Assembly.Load钦定了先后集名],所以,在反射时,就会去钦定的命名空间里找对应的类。那样就能找到非本主次集下的类了。

  1. Type  t  = 
    Type.GetType(“System.Data.DataTable,System.Data,Version=1.0.3300.0, 
    Culture=neutral,  PublicKeyToken=b77a5c561934e089”);
    1. DataTable  table  =  (DataTable)Activator.CreateInstance(t);

[Assembly.Load钦命了程序集名]那句话不佳掌握?

复制代码

无妨,换个表明,Assembly.Load钦点了命名空间的名目,所以反射时,会去那么些命名空间里找类,那样是或不是就好领会了。

例2:根据有参数的构造器创制对象

Assembly

  1. namespace  TestSpace  
  2. {
  3.   public  class  TestClass
  4.       {
  5.       private  string  _value;
  6.       public  TestClass(string  value)  
  7.     {
  8.       _value=value;
  9.       }
  10.   }
  11. }
  12. Type  t  =  Type.GetType(“TestSpace.TestClass”);
  13. Object[]  constructParms  =  new  object[]  {“hello”}; 
    //构造器参数
  14. TestClass  obj  = 
    (TestClass)Activator.CreateInstance(t,constructParms);

Assembly的留存让反射变得专程灵巧,其中Assembly.Load不止能够导入大家引进的程序集(或命名空间)。

复制代码

也足以导入大家未引入程序集的dll。调用格局如下:

把参数依据顺序放入二个Object数组中即可

System.Reflection.Assembly o = System.Reflection.Assembly.Load("mscorlib.dll");

6、怎样收获格局以及动态调用方法

Assembly导入了程序集后,还足以不借助Activator来援救,本身就足以创设类。如下:

  1. namespace  TestSpace
  2. {
  3.       public  class  TestClass  {
  4.           private  string  _value;
  5.           public  TestClass()  {
  6.           }
  7.           public  TestClass(string  value)  {
  8.                 _value  =  value;
  9.           }
    1.           public  string  GetValue(  string  prefix  )  {
  10.           if(  _value==null  )
  11.           return  “NULL”;
  12.           else
  13.             return  prefix+”  :  “+_value;
  14.             }
    1.             public  string  Value  {
  15. set  {
  16. _value=value;
  17. }
  18. get  {
  19. if(  _value==null  )
  20. return  “NULL”;
  21. else
  22. return  _value;
  23. }
  24.             }
  25.       }
  26. }
Assembly assembly = Assembly.Load("Syntax");
Kiba kiba = (Kiba)assembly.CreateInstance("Syntax.Kiba");

复制代码

1对同学可能会担心品质,会认为这么反射,会使程序变慢。

地点是3个大致的类,包涵四个有参数的构造器,一个GetValue的主意,贰个Value属性,我们得以由此艺术的称号来收获方法并且调用之,如:

有那种想法的同桌,其实您曾经是在过度掌握语法了。那种地方的代码品质其实是足以不用关爱的。

  1. //获取类型音讯
  2. Type  t  =  Type.GetType(“TestSpace.TestClass”);
  3. //构造器的参数
  4. object[]  constuctParms  =  new  object[]{“timmy”};
  5. //依照项目创造对象
  6. object  dObj  =  Activator.CreateInstance(t,constuctParms);
  7. //获取形式的音讯
  8. MethodInfo  method  =  t.GetMethod(“GetValue”);
  9. //调用方法的局地标志位,那里的含义是Public并且是实例方法,那也是暗许的值
  10. BindingFlags  flag  =  BindingFlags.Public  | 
    BindingFlags.Instance;
  11. //GetValue方法的参数
  12. object[]  parameters  =  new  object[]{“Hello”};
  13. //调用方法,用三个object接收重返值
  14. object  returnValue  = 
    method.Invoke(dObj,flag,Type.DefaultBinder,parameters,null);

那正是说,到底会不会变慢呢?

复制代码

答案是那样的,倘诺您是运用完全限定名来反射,速度即是同一的。若是是反射时,只写了叁个类名,那么速度就会变慢。因为它要遍历全数的命名空间,去找那一个类。

质量与方法的调用鄂尔多斯小异,大家也能够参见MSDN

即,只要反射时把类的命名空间写全,那么速度就不会慢。

七、动态创造委托
 
      委托是C#中贯彻事件的根底,有时候不可防止的要动态的创建法委员会委员托,实际上委托也是1种档次:System.Delegate,全体的信托都是从那几个类派生的
 
     
System.Delegate提供了一部分静态方法来动态创立三个委托,比如二个委托:

二,函数反射

  1. namespace  TestSpace  {
  2.       delegate  string  TestDelegate(string  value);
  3.       public  class  TestClass  {
  4. public  TestClass()  {
  5.                   }
  6.                   public  void  GetValue(string  value)  {
  7.                           return  value;
  8.                   }
  9.         }
  10. }

函数的反射应用主即使使用类MethodInfo类反射,下边先看下基础应用。

复制代码

public static void ExcuteMethod()
{ 
    Assembly assembly = Assembly.Load("Syntax"); 
    Type type = assembly.GetType("Syntax.Kiba", true, false);
    MethodInfo method =  type.GetMethod("PrintName"); 
    object kiba = assembly.CreateInstance("Syntax.Kiba");
    object[] pmts = new object[] { "Kiba518" };
    method.Invoke(kiba, pmts);//执行方法  
}
public class Kiba
{
    public string Name { get; set; }
    public void PrintName(string name)
    {
        Console.WriteLine(name);
    }
}

运用示例:

有个别同室第1当即上去大概会有点不适于,因为接近很多类都是我们不平日用的。那也不可能,因为那是三个进阶的进程,必须经历从面生到熟练。当您熟识了这么的代码后,就代表你的技术水平又发展了叁个台阶。

  1. TestClass  obj  =  new  TestClass();
    1. //获取项目,实际上那里也得以直接用typeof来收获项目
  2. Type  t  =  Type.GetType(“TestSpace.TestClass”);
  3. //创制代理,传入类型、创立代理的靶子以及艺术名称
  4. TestDelegate  method  = 
    (TestDelegate)Delegate.CreateDelegate(t,obj,”GetValue”);
    1. String  returnValue  =  method(“hello”);

上面讲解1些那个代码。

复制代码

先是我们导入了命名空间,接着大家获取了该命名空间下Kiba那一个类的档次;接下去大家经过那个连串来收获钦赐名称的函数。


接下来大家因此Assembly成立了二个Kiba的实例,接着定义了一个参数的Object数组,因为Kiba类下的函数PrintName唯有3个参数,所以,咱们只为这些Object数组添加3个指标[Kiba518]。

别的一篇关于反射的篇章

末尾,大家透过method.Invoke来调用那么些函数,由于是反射,所以调用时,必要钦定Kiba类的实例对象和入参。

—————原来的文章如下——————

诸如此类,函数的反射就达成了。

反射的定义:审查元数据并征集有关它的类型消息的力量。元数据(编译将来的最宗旨数据单元)正是一大堆的表,当编写翻译程序集或许模块时,编写翻译器会创建3个类定义表,二个字段定义表,和一个办法定义表等。
         
System.reflection命名空间包罗的多少个类,允许你反射(解析)这几个元数据表的代码   

三,属性反射

System.Reflection.Assembly 
System.Reflection.MemberInfo
System.Reflection.EventInfo
System.Reflection.FieldInfo
System.Reflection.MethodBase
System.Reflection.ConstructorInfo
System.Reflection.MethodInfo
System.Reflection.PropertyInfo
System.Type
以下是地点多少个类的施用方法:
(1)使用Assembly定义和加载程序集,加载在先后集清单中列出模块,以及之后程序集中查找类型并创制该项目标实例。 
(二)使用Module领悟蕴涵模块的次序集以及模块中的类等,还足以获得在模块上定义的全部全局方法或任何特定的非全局方法。 
(3)使用ConstructorInfo领会构造函数的名号、参数、访问修饰符(如pulic
或private)和兑现详细音信(如abstract或virtual)等。使用Type的GetConstructors或
GetConstructor方法来调用特定的构造函数。 
(四)使用MethodInfo掌握方法的称号、再次回到类型、参数、访问修饰符(如pulic
或private)和落实详细消息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的方法。 
(五)使用FiedInfo精晓字段的称呼、访问修饰符(如public或private)和达成详细音信(如static)等,并拿走或安装字段值。 
(陆)使用伊夫ntInfo通晓事件的称呼、事件处理程序数据类型、自定义属性、申明类型和反光类型等,添加或移除事件处理程序。 
(七)使用PropertyInfo领悟属性的称呼、数据类型、注脚类型、反射类型和只读或可写状态等,获取或安装属性值。 
(八)使用ParameterInfo精晓参数的称呼、数据类型、是输入参数依然出口参数,以及参数在艺术签名中的地方等。
反射的层次模型:
金沙注册送58 1
(注:层次间都是1对多的涉嫌)

属性反射是用PropertyInfo类来兑现,上边看基础的性情反射。

 

public static void ExcuteProperty()
{
    Kiba kiba = new Kiba();
    kiba.Name = "Kiba518";
    object name = ReflectionSyntax.GetPropertyValue(kiba, "Name");
    Console.WriteLine(name); 
} 
public static object GetPropertyValue(object obj, string name)
{
    PropertyInfo property = obj.GetType().GetProperty(name);
    if (property != null)
    {
        object drv1 = property.GetValue(obj, null);
        return drv1;
    }
    else
    {
        return null;
    } 
}

反射的职能:
1、能够接纳反射动态地创设项目的实例,将项目绑定到存活对象,或从现有对象中收获项目
二、应用程序须要在运维时从某些特定的次第集中载入3个特定的档次,以便完毕有个别职责时能够用到反射。
三、反射首要利用与类库,这一个类库须要精晓三个门类的定义,以便提供越来越多的职能。

如代码所示,首先大家定义了1个Kiba的指标,并为Name赋值,然后大家透过GetPropertyValue方法,传递了Kiba对象和要获得值的天性名称。

行使大旨:
壹、现实应用程序中很少有应用程序必要采纳反射类型
2、使用反射动态绑定供给捐躯质量
三、某个元数据消息是无法透过反射获取的
4、有些反射类型是特地为那么些clr
开发编写翻译器的支付使用的,所以您要发现到不是有所的反光类型都以相符各种人的。

GetPropertyValue函数里透过采纳PropertyInfo实现了反光。

 

一部分同学可能会认为,那几个很鸡肋,既然已经赢得指标,还反射做如何,直接得到就足以了呀。

反射appDomain 的次第集:

别着急,大家接下去1起看反射的架构应用。

当你要求反射AppDomain 中隐含的保有程序集,示例如下:
static void Main
{
       //通过GetAssemblies 调用appDomain的享有程序集
       foreach (Assembly assem in
Appdomain.currentDomain.GetAssemblies())
      {
       //反射当前先后集的消息
            reflector.ReflectOnAssembly(assem)
      }
}

反射的架构应用

表达:调用AppDomain 对象的GetAssemblies 方法
将再次回到2个由System.Reflection.Assembly成分组成的数组。

 框架编写的基本指标之1,是统1系统秩序。那么怎样是系统秩序呢?

反射单个程序集:

 首先大家看下系统的结缘,系统个平凡是由子系统,程序集,类,函数那四局地组成。如下图所示。

地点的措施讲的是反射AppDomain的具有程序集,大家能够呈现的调用当中的贰个程序集,system.reflecton.assembly
类型提供了上面三种艺术:
1、Load 方法:极力推荐的一种方式,Load
方法包罗二个程序集标志并载入它,Load
将引起CL宝马X5把政策应用到程序集上,先后在大局程序集缓冲区,应用程序基目录和民用路径下边查找该程序集,假若找不到该程序集系统抛出万分
二、LoadFrom
方法:传递贰个顺序集文件的门径名(包涵扩充名),CL奥迪Q5会载入您钦赐的那几个程序集,传递的那么些参数无法包罗别的关于版本号的信息,区域性,和公钥音信,借使在钦赐路线找不到程序集抛出特别。
3、LoadWithPartialName:永远不要选择这些主意,因为应用程序无法确定再在载入的顺序集的版本。该措施的唯一用途是帮衬那二个在.Net框架的测试环节使用.net
框架提供的某种行为的客户,那几个方法将最终被遗弃不用。

金沙注册送58 2

专注:system.AppDomain 也提供了1种Load 方法,他和Assembly的静态Load
方法不一致,AppDomain的load
方法是一种实例方法,再次回到的是三个对先后集的引用,Assembly的静态Load
方发将程序集按值封装发回给发出调用的AppDomain.尽量防止接纳AppDomain的load
方法

既然如此系统由子系统,程序集,类,函数那三个基础成分结合,那么系统秩序,自然指的便是那两个要素的秩序。而那八个成分最难形成秩序的就是函数了。

接纳反射获取类型新闻:

很鲜明,任何的花色都留存重复的函数,恐怕效率看似的函数。而根本杜绝那种气象,显明是不容许的。那么大家只好硬着头皮是规划会幸免再一次成分的框架了。而反射,正是为此而留存的。

前边讲完了有关程序集的反光,上面在讲一下反光层次模型中的第多少个层次,类型反射
四个简约的应用反射获取类型消息的事例:

反射的架构应用

using system;
using sytem.reflection;
class reflecting 
{
       static void Main(string[]args)
       {
             reflecting reflect=new reflecting();//定义三个新的本身类
             //调用一个reflecting.exe程序集

具体中的框架因为那样那样的因由,会有蹊跷的统一筹划,所以拘泥于1种设计方式是丘脑下部损伤的,实战中要出头设计形式1起使用,局地设计有时只取设计形式中一部分也得以。那样才能促成项目标量身定制。

             assembly myAssembly =assembly.loadfrom(“reflecting.exe”)
             reflect.getreflectioninfo(myAssembly);//获取反射消息
       }

就此,那里只介绍一种实战的架构应用,一种选择反射的框架基础结构。上面请框架基础代码。

       //定义三个获得反射内容的秘籍
       void getreflectioninfo(assembly myassembly)
       {
             type[] typearr=myassemby.Gettypes();//获取项目
             foreach (type type in typearr)//针对每一种系列获取详细新闻
            {
                   //获取项指标布局音信
                  constructorinfo[]
myconstructors=type.GetConstructors;

public class Client
{
    public void ExcuteGetNameCommand()
    {
        Proxy proxy = new Proxy();
        GetNameCommand cmd = new GetNameCommand();
        ResultBase rb = proxy.ExcuteCommand(cmd);
    } 
} 
public class Proxy
{
    public ResultBase ExcuteCommand(CommandBase command)
    {
        var result = HandlerSwitcher.Excute(command);
        return result as ResultBase;
    }
}
public class HandlerSwitcher
{
    private const string methodName = "Excute";//约定的方法名
    private const string classNamePostfix = "Handler";//约定的处理Command的类的名称的后缀 
    //获取命名空间的名称
    public static string GetNameSpace(CommandBase command)
    {
        Type commandType = command.GetType();//获取完全限定名
        string[] CommandTypeNames = commandType.ToString().Split('.');
        string nameSpace = "";
        for (int i = 0; i < CommandTypeNames.Length - 1; i++)
        {
            nameSpace += CommandTypeNames[i];
            if (i < CommandTypeNames.Length - 2)
            {
                nameSpace += ".";
            }
        } 
        return nameSpace;
    }

    public static object Excute(CommandBase command)
    {
        string fullName = command.GetType().FullName;//完全限定名
        string nameSpace = GetNameSpace(command);//命名空间  
        Assembly assembly = Assembly.Load(nameSpace);
        Type handlerType = assembly.GetType(fullName + classNamePostfix, true, false);
        object obj = assembly.CreateInstance(fullName + classNamePostfix);
        MethodInfo handleMethod = handlerType.GetMethod(methodName);//获取函数基本信息
        object[] pmts = new object[] { command }; //传递一个参数command
        try
        {
            return handleMethod.Invoke(obj, pmts);
        }
        catch (TargetInvocationException tie)
        {
            throw tie.InnerException;
        }
    }
}
public class GetNameCommandHandler
{
    public ResultBase Excute(CommandBase cmd)
    {
        GetNameCommand command = (GetNameCommand)cmd;
        ResultBase result = new ResultBase();
        result.Message = "I'm Kiba518";
        return result;
    }
}
public class GetNameCommand: CommandBase
{  
} 
public class CommandBase
{ 
    public int UserId { get; set; } 

    public string UserName { get; set; } 

    public string ArgIP { get; set; } 
}
public class ResultBase
{ 
    public string Message { get; set; } 
}

                 //获取项指标字段音讯
                 fieldinfo[] myfields=type.GetFiedls()

代码中框架很简短,主要指标是促成2个代理,用于拍卖继承了CommandBase的类的代办。

                 //获取格局消息
                 MethodInfo   myMethodInfo=type.GetMethods();

即,客户端,不论传来什么样的Command,只要它是再而三自CommandBase的,这些代理都会找到呼应的拍卖类,并履行拍卖,且重临结果。

                 //获取属性音讯
                 propertyInfo[] myproperties=type.GetProperties

为了更清晰的敞亮那段代码,大家得以参照下边这几个流程图。结合了图片在来看代码,架构就会更鲜明。

                 //获取事件音讯
                 EventInfo[] Myevents=type.GetEvents;
           }
      }
}
其他三种得到type对象的格局:
一、System.type  
参数为字符串类型,该字符串必须钦命项指标完好名称(包括其取名空间)
二、System.type 提供了三个实例方法:GetNestedType,GetNestedTypes
三、Syetem.Reflection.Assembly
类型提供的实例方法是:GetType,GetTypes,GetExporedTypes
4、System.Reflection.Moudle
提供了那几个实例方法:GetType,GetTypes,FindTypes

金沙注册送58 3

设置反光类型的成员:

那几个大致的框架中,使用了一个概念,叫做约定优先条件,也号称约定优于配备;喜欢概念的同伴能够自动百度。

反射类型的分子就算反射层次模型中最上边包车型大巴一层数据。咱们得以由此type对象的GetMembers
方法取得3个体系的成员。假如大家应用的是不带参数的GetMembers,它只回去该品种的公家定义的静态变量和实例成员,咱们也能够因而选择带参数的
GetMembers通过参数设置来回到内定的种类成员。具体参数参考msdn
中system.reflection.bindingflags 枚举类型的详尽说明。

框架中利用的多少个约定如下:

例如:
//设置需求回到的类其余分子内容
bindingFlags
bf=bingdingFlags.DeclaredOnly|bingdingFlags.Nonpublic|BingdingFlags.Public;
foreach (MemberInfo mi int t.getmembers(bf))
{
       writeline(mi.membertype)    //输出内定的门类成员
}

先是个是,处理Command的类必须后缀名是Command的类名+Handler结尾。

透过反射创立项指标实例:

第二个是,处理Command的类中的处理函数名必须为Excute。

经过反射能够获取程序集的档次,大家就能够依据取得的次序集类型来创制该项目新的实例,那也是前方提到的在运作时创制对象完成晚绑定的效力
咱俩得以因此下边包车型大巴多少个措施达成:
一、System.Activator
的CreateInstance方法。该格局再次来到新对象的引用。具体行使办法参见msdn
二、System.Activator 的createInstanceFrom
与上一个主意类似,然则需求钦点项目及其程序集
3、System.Appdomain
的方法:createInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap
肆、System.type的InvokeMember实例方法:那一个法子重返七个与传播参数相符的构造函数,并组织该品种。
5、System.reflection.constructinfo 的Invoke实例方法

其实概念便是供大家使用的,会用即可;学习的进度中,概念之类的术语,有个印象即可。

反射类型的接口:

PS:为了阅读方便,那其中的类都集中写在了3个命名空间之下了,如若有想行使那种设计格局的同桌,请根据自个儿项目所需举办扩张。

要是您想要获得贰个系列继承的保有接口集合,能够调用Type的FindInterfaces
GetInterface只怕GetInterfaces。全体那么些方式只能回到该类型直接接轨的接口,他们不会再次来到从一个接口继承下来的接口。要想回来接口的根底接口必须再次调用上述格局。


反射的习性:

这么,大家就透过反射达成了三个13分简便的框架,通过选择这些框架,会让代码变的越来越简明。

行使反射来调用类型或然触发方法,只怕访问八个字段大概性质时clr
须求做更加多的干活:校验参数,检查权限等等,所以速度是相当慢的。所以尽量不要采取反射实行编制程序,对于打算编写叁个动态构造类型(晚绑定)的应用程序,能够利用以下的两种格局进行代替:
1、通过类的接续关系。让该项目从三个编写翻译时可见的根底项目派生出来,在运作时生成该品种的2个实例,将对其的引用放到其基础项指标一个变量中,然后调用该基础项指标虚方法。
二、通过接口完结。在运维时,塑造该项目标八个实例,将对其的引用放到其接口类型的一个变量中,然后调用该接口定义的虚方法。
3、通过信托完成。让该项目达成3个艺术,其名目和原型都与1个在编写翻译时就已知的信托符合。在运行时先构造该项目标实例,然后在用该格局的指标及称号构造出该信托的实例,接着通过信托调用你想要的法门。那几个办法相对与前方几个法子所作的劳作要多壹些,功效更低一些。

而为了落成每一个模块的简练,反射也将会被封装在挨家挨户模块的最底层,所以,反射毫无疑问,正是框架设计的基础。

 

反射与特点

个体操作方案:

反射在系统中另二个主要应用正是与特点的结合使用。

源DLL类:

在某些周旋复杂的种类中,难免会境遇一些光景,要讲对象中的1有的属性清空,只怕要收获对象中的有些质量赋值。常常我们的落到实处方式就是手写,一个多少个的赋值。

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web.UI;
using System.Collections;

而使用反射并整合特性,完全能够简化那种复杂操作的代码量。

namespace cn.SwordYang
{

 public partial class ReflectionSyntax
 {
     public void ExcuteKibaAttribute()
     {
         Kiba kiba = new Kiba();
         kiba.ClearName = "Kiba518";
         kiba.NoClearName = "Kiba518";
         kiba.NormalName = "Kiba518";
         ClearKibaAttribute(kiba);
         Console.WriteLine(kiba.ClearName);
         Console.WriteLine(kiba.NoClearName);
         Console.WriteLine(kiba.NormalName);
     }
     public void ClearKibaAttribute(Kiba kiba)
     {
         List<PropertyInfo> plist = typeof(Kiba).GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).ToList();//只获取Public的属性
         foreach (PropertyInfo pinfo in plist)
         {
             var attrs = pinfo.GetCustomAttributes(typeof(KibaAttribute), false);
             if (null != attrs && attrs.Length > 0)
             { 
                 var des = ((KibaAttribute)attrs[0]).Description; 
                 if (des == "Clear")
                 {
                     pinfo.SetValue(kiba, null); 
                 }
             }
         }
     } 
 } 
 public class Kiba
 {
     [KibaAttribute("Clear")]
     public string ClearName { get; set; }
     [KibaAttribute("NoClear")]
     public string NoClearName { get; set; }
     public string NormalName { get; set; }

 }
 [System.AttributeUsage(System.AttributeTargets.All)]
 public class KibaAttribute : System.Attribute
 {
     public string Description { get; set; }
     public KibaAttribute(string description)
     {
         this.Description = description;
     }
 }

    public class TextClass:System.Web.UI.Page
    {

如上述代码所示, 大家通过反射,将有着KibaAttribute天性的,且描述为Clear的品质,清空了。

public static void RunJs(Page _page, string Source)
        {
            _page.ClientScript.RegisterStartupScript(_page.GetType(),
“”, “<script type=\”text/javascript\”>” + Source +
“;</script>”);

当然为了壹性子情这么做不值得,但借使3个对象有陆15个天性的时候,这么做就值得了。

        }

既然能解决属性的数量,那么自然就足以为属性赋值。至于哪些实现反射赋值,相信大家能够举1反3。

}

反射+性格最常见的风貌

}

反射+天性一起使用,最常见的景观正是用ADO.NET从数据库查询出DataTable的数额,然后将DataTable的多少转换到Model实体类型。

//调用代码

咱俩在开发中,为了让实体越发充血,往往会对数码实体增添一些个性和办法。(什么是充血?充血正是充血模型,有趣味的同学能够自动百度询问下,简单说便是为实体加属性和艺术。)

System.Reflection.Assembly ass =
Assembly.LoadFrom(Server.MapPath(“bin/swordyang.dll”)); //加载DLL
            System.Type t =
ass.GetType(“cn.SwordYang.TextClass”);//得到类型
            object o = System.Activator.CreateInstance(t);//创制实例

那么,在用反射,将DataTable转存到Model实体的时候,遍历属性并赋值的时候,就会多遍历那么四次。

            System.Reflection.MethodInfo mi =
t.GetMethod(“RunJs”);//拿到格局

一旦只是一个实体,那么,多遍历五遍也没影响。但,如若是数十万的数量,那那多一遍的遍历影响就大了。

            mi.Invoke(o, new object[] {
this.Page,”alert(‘测试反射机制’)”});//调用方法

而用反射+天性,就能够减小那个额外遍历次数。

反射机制对应设计格局中的策略方式。

讲了如此多为何不给代码呢?

因为自个儿觉着,将上边的情节全知晓的同校,应该可以说,已经框架启蒙了。那么,这几个反光+天性的DataTable转数据实体,假如能友好写出来,就到底框架入门了。所以,那里给咱们留下了多个演习的半空中。

小心,小编那里说的是框架,而不是架设。

框架与架构的分裂是这么的,框架是个名词,而框架结构是个动词。框架即便很在行了,也丢失得足以架构的很好。那几个大家依旧要留意区分。

结语

看完了整篇小说,有的同学恐怕会有问号,这么生疏的PropertyInfo和MethodInfo真的有人会用吗?都以Copy代码,然后使用呢。

答案是,当然有人能够纯熟应用。反射是架构师的入门基础,任何八个[可以实战]的架构师,都亟待随时随处的能够手写出反射,因为优化框架是他俩的权力和责任。

从而,对此有所疑虑的伙伴,可以全力以赴练习了,将委托融入血液,是高档软件工程师的功底,而将反射融入血液,正是架构师的底子了。

C#语法——元组类型

C#语法——泛型的有余用到

C#语法——await与async的不易打开药方式

C#语法——委托,架构的血液

C#语法——事件,逐步边缘化的二哥。

C#语法——音信,MVVM的大旨技术。

我对C#的认知。


注:此文章为原创,欢迎转发,请在篇章页面显明地点给出此文链接!
若你认为那篇小说还能够,请点击下右下角的【推荐】,卓殊谢谢!
只要您觉得那篇小说对你有所扶助,那就不妨支付宝小小打赏一下呢。 

金沙注册送58 4

 

相关文章

网站地图xml地图