架构师的入门基础

前言

小编理解:

反射

反射

编制程序其实便是写代码,而写代码目标正是完毕工作,所以,语法和框架也是为了兑现工作而存在的。因而,不管多么巨大上的目的,实质上都以业务。

装配件:Assembly(程序集)

简介

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

  通过反射,即可对每1种档次了如指掌,并且也得以透过反射创立、调用和做客对象,尽管在编写翻译时不鲜明该指标的类型。

  程序集带有模块,模块包括类型,而项目涵盖成员。反射提供包装程序集、模块和档次的目的。可以动用反射动态地成立项目标实例,将品种绑定到现有对象,或从现有对象中获得项目。

简介

  反射是
.NET中的首要体制,通过反射,能够在运作时得到程序或程序集中类型(包涵class、struct、delegate、interface 和 enum 等)的分子和分子的音信。

  通过反射,即可对每1种档次了如指掌,并且也可以通过反射创造、调用和走访对象,固然在编写翻译时不明确该目的的档次。 

  程序集带有模块,模块包罗类型,而项目涵盖成员。反射提供包装程序集、模块和类其他靶子。可以运用反射动态地开创项目标实例,将品种绑定到现有对象,或从现有对象中赢得项目。

 

因此,笔者觉得并非把写代码上涨到科学的可观。回升到形式就足以了,因为艺术自己也尚无高度。。。。

晚绑定:中期绑定

优缺点

  优点:

  1. 增长了程序的灵活性和扩大性;
  2. 下落耦合性;
  3. 它同意程序创设和控制别的类的目的,无需提前硬编码指标类。

  缺点:

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

优缺点

  优点:

  1. 加强了先后的八面后珑和扩张性;
  2. 下落耦合性;
  3. 它同意程序创造和操纵其余类的靶子,无需提前硬编码目的类。

  缺点:

  1. 天性:使用反射基本上是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 命名空间的类提供一种专用格局的反射,使您可见在运转时生成类型。

 

有趣味是好事,但就算知道了反光的本质,领悟了反光是什么规划的,你技术也没怎么质的变动。因为,技术水平最后照旧要促成到应用上。

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

反射的大致用法

  命名空间: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、
命名空间与装配件的涉嫌
三、
运维期获得类型新闻有哪些用
肆、
怎么着使用反射获取项目
伍、
怎么着依据项目来动态创设对象
六、
如何获取格局以及动态调用方法
7、
动态创制委托

二个普遍的示范用法

  大家1初叶学习叁层框架结构的时候,都应当会融洽接着导师动手制作1个SqlHelper
的吧,那里本人截取一个由此反射读取数据库数据并填充到一个对象的天性上,通过轮回遍历,最平生成一个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):属性赋值,选拔相应的对象开展赋值。


反骨仔

微软官方文书档案

 3个科学普及的演示用法

  大家1初步攻读3层架构的时候,都应该会协调随后导师动手制作二个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(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;
        }

  简单解析利用反射的代码:

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

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

    (3)propertyInfo.SetValue(entity,
val):属性赋值,采用相应的对象开始展览赋值。

 

 


【博主】反骨仔

【原文】 

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

 

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

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


 
     
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二多少个命名空间,而且各表明了多个类,那样是一点一滴能够的,然后大家在三个应用程序中援引装配件A,那么在那一个应用程序中,大家能观察N壹上边包车型客车类为AC1和AC二,N2上面包车型客车类为AC3和AC肆。
 
     
接着咱们去掉对A的引用,加上对B的引用,那么大家在这么些应用程序下能看到的N一下边包车型地铁类成为了BC一和BC二,N二上面也同样。
 
     
假设我们同时援引那四个装配件,那么N1上面我们就能收看多个类:AC壹、AC二、BC一和BC二。

反射能够通过类名的字符串来创设类,能够通过函数名的字符串和属性名的字符串,来调用类下的函数和性质。

 
     
到此处,大家得以领略3个定义了,命名空间只是说多美滋(Karicare)个门类是那多少个族的,比如有人是回族、有人是独龙族;而装配件表美赞臣个品种住在哪儿,比如有人住在新加坡市、有人住在东京;那么日本首都有德昂族人,也有仫佬族人,北京有哈尼族人,也有柯尔克孜族人,那是不争执的。

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

 
     
下边大家说了,装配件是2个类型居住的地方,那么在三个程序中要使用三个类,就非得告诉编写翻译器那几个类住在何处,编写翻译器才能找到它,相当于说必须引用该装配件。
 
     
那么只要在编写程序的时候,或然不鲜明那么些类在哪个地方,仅仅只是知道它的称号,就不能够应用了呢?答案是能够,这正是反射了,正是在程序运维的时候提供该品种的地方,而去找到它。
有趣味的话,接着往下看吗。

会有那种难题的同班,先别着急,继续往下看,反射既然存在,就一定有存在的道理。

三、运转期得到类型音信有哪些用
 
     
有人也许难题,既然在付出时就可见写好代码,干嘛还内置运维期去做,不光繁琐,而且效用也受影响。
那就是个例外的题材了,就跟早绑定和晚绑定壹样,应用到区别的场子。有的人反对晚绑定,理由是消耗作用,然而不少人在分享虚函数带来的益处的时侯还未有察觉到她已经用上了晚绑定。那么些标题说开去,不是3言两语能讲明白的,所以就点到停止了。
 
     
作者的见识是,晚绑定能够带来许多规划上的惠及,合适的使用能够大大进步程序的复用性和灵活性,不过别的事物都有两面性,使用的时侯,须要再3衡量。

反射的底蕴运用

跟着说,运维期获得类型新闻到底有啥样用吗?
恐怕举个例子来注脚,很多软件开发者喜欢在祥和的软件中留下一些接口,其余人能够编写一些插件来扩展软件的机能,比如笔者有二个媒体播放器,笔者希望以往能够很有利的扩大识其他格式,那么我声澳优(Ausnutria Hyproca)个接口:

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

本条接口中蕴藏三个Extension属性,那性情子重临帮助的壮大名,另八个办法重临二个解码器的目的(那里自个儿壹旦了1个Decoder的类,这一个类提供把公文流解码的机能,扩张插件能够派生之),通过解码器对象自作者就可以分解文件流。
那正是说作者鲜明全体的解码插件都不能够不派生1个解码器,并且实现这一个接口,在GetDecoder方法中回到解码器对象,并且将其品种的称谓配置到本身的布署文件之中。
那样的话,笔者就不必要在支付播放器的时侯知道以往扩展的格式的门类,只必要从布局文件中拿走以后具有解码器的项目名称,而动态的创制媒体格式的对象,将其转移为IMediaFormat接口来行使。

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

那正是3个反光的一花独放应用。

中间字符串”Syntax.Kiba”是2个完全限定名。什么是全然限定名?完全限定名就是命名空间+类名。在反射的时候,需求我们传递完全限定名来分明到底要去哪个命名空间,找哪位类。

4、怎么着利用反射获取项目
 
      首先大家来看怎么获取类型音信。
 
      获得类型信息有三种方法,壹种是得到实例对象
 
     
那些时侯笔者偏偏是得到这几个实例对象,获得的秘籍大概是2个object的引用,可能是1个接口的引用,可是自个儿并不知道它的适度品种,作者索要领会,那么就足以由此调用System.Object上注明的艺术GetType来博取实例对象的连串对象,比如在有个别方法内,小编索要看清传递进入的参数是还是不是落实了有些接口,假如完成了,则调用该接口的3个措施:

在代码中咱们还足以见见,获取项指标章程有三种,壹种是较复杂的,壹种是归纳的。

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

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

复制代码

两边有哪些分别呢?

别的一种得到项目标不二秘诀是透过Type.GetType以及Assembly.GetType方法,如:
 
            Type  t  =  Type.GetType(“System.String”);
 
     
要求专注的是,前边大家讲到了命名空间和装配件的涉及,要摸索1个类,必须内定它所在的装配件,或许在早就收获的Assembly实例下面调用GetType。
 
     
本装配件中项目能够只写类型名称,另八个见仁见智是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提供了点子来根据项目动态创造对象,比如创制1个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");

陆、怎样获取方式以及动态调用方法

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个简易的类,包罗二个有参数的构造器,贰个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);

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

复制代码

答案是这般的,尽管您是选拔完全限定名来反射,速度正是千篇1律的。如若是反光时,只写了3个类名,那么速度就会变慢。因为它要遍历全数的命名空间,去找那么些类。

质量与措施的调用东营小异,我们也能够参见MSDN

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

七、动态创立委托
 
      委托是C#中落到实处事件的底子,有时候不可幸免的要动态的制造委托,实际上委托也是一种档次:System.Delegate,全数的嘱托都以从这些类派生的
 
     
System.Delegate提供了有的静态方法来动态创设3个寄托,比如一个委托:

2,函数反射

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

上边讲解壹些那个代码。

复制代码

先是我们导入了命名空间,接着大家获取了该命名空间下Kiba这几个类的品类;接下去我们经过这一个体系来博取钦赐名称的函数。


接下来我们透过Assembly创制了3个Kiba的实例,接着定义了1个参数的Object数组,因为Kiba类下的函数PrintName唯有一个参数,所以,大家只为这么些Object数组添加贰个指标[Kiba518]。

此外1篇关于反射的篇章

终极,我们由此method.Invoke来调用那些函数,由于是反射,所以调用时,需求内定Kiba类的实例对象和入参。

—————最初的作品如下——————

这么,函数的反光就兑现了。

反射的概念:审查元数据并采访有关它的类型音讯的能力。元数据(编写翻译现在的最宗旨数据单元)正是一大堆的表,当编写翻译程序集或然模块时,编译器会创设贰个类定义表,2个字段定义表,和二个措施定义表等。
         
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方法来调用特定的措施。 
(5)使用FiedInfo掌握字段的名目、访问修饰符(如public或private)和贯彻详细新闻(如static)等,并赢得或安装字段值。 
(陆)使用伊夫ntInfo精晓事件的名称、事件处理程序数据类型、自定义属性、证明类型和反光类型等,添加或移除事件处理程序。 
(柒)使用PropertyInfo明白属性的名称、数据类型、申明类型、反射类型和只读或可写状态等,获取或设置属性值。 
(8)使用ParameterInfo驾驭参数的称谓、数据类型、是输入参数依旧出口参数,以及参数在艺术签名中的地点等。
反射的层次模型:
美高梅开户网址 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;
    } 
}

反射的效果:
一、能够选用反射动态地制造项目标实例,将项目绑定到存活对象,或从现有对象中拿走项目
②、应用程序须求在运维时从有个别特定的次第集中载入3个特定的档次,以便达成某些任务时能够用到反射。
3、反射主要使用与类库,那些类库须求精通1个档次的概念,以便提供更加多的效劳。

如代码所示,首先大家定义了两个Kiba的对象,并为Name赋值,然后大家经过GetPropertyValue方法,传递了Kiba对象和要得到值的性质名称。

使用大旨:
1、现实应用程序中很少有应用程序须要利用反射类型
贰、使用反射动态绑定必要就义品质
叁、有些元数据消息是无法通过反射获取的
四、有些反射类型是专程为那些clr
开发编写翻译器的花费使用的,所以您要发现到不是装有的反光类型都以契合各种人的。

GetPropertyValue函数里透过应用PropertyInfo实现了反光。

 

局地同学也许会认为,这一个很鸡肋,既然已经得到指标,还反射做哪些,间接获取就能够了呀。

反射appDomain 的主次集:

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

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

反射的架构应用

声明:调用AppDomain 对象的GetAssemblies 方法
将回来3个由System.Reflection.Assembly成分组成的数组。

 框架编写的中坚目标之1,是联合系统秩序。那么哪些是系统秩序呢?

反射单个程序集:

 首先大家看下系统的组合,系统个日常是由子系统,程序集,类,函数这肆部分组成。如下图所示。

上边的艺术讲的是反射AppDomain的保有程序集,大家得以显得的调用个中的1个程序集,system.reflecton.assembly
类型提供了下边三种格局:
一、Load 方法:极力推荐的一种方法,Load
方法包涵一个程序集标志并载入它,Load
将唤起CL福特Explorer把政策应用到程序集上,先后在全局程序集缓冲区,应用程序基目录和私家路径下边查找该程序集,固然找不到该程序集系统抛出万分
二、LoadFrom
方法:传递二个顺序集文件的门径名(包含扩充名),CL奥德赛会载入您钦命的这么些程序集,传递的这些参数无法包蕴其余关于版本号的音讯,区域性,和公钥音信,借使在内定路线找不到程序集抛出尤其。
叁、LoadWithPartialName:永远不要使用那个主意,因为应用程序不可能分明再在载入的主次集的本子。该措施的唯一用途是支持那一个在.Net框架的测试环节使用.net
框架提供的某种行为的客户,那些方法将最后被撤销不用。

美高梅开户网址 2

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

既然如此系统由子系统,程序集,类,函数那多个基础成分构成,那么系统秩序,自然指的正是那多个成分的秩序。而那三个成分最难形成秩序的正是函数了。

行使反射获取类型音信:

很显著,任何的种类都留存重复的函数,可能功用类似的函数。而根本杜绝那种状态,鲜明是不容许的。那么我们只能硬着头皮是安排性会防止重新元素的框架了。而反射,正是为此而存在的。

前方讲完了关于程序集的反射,上面在讲一下反光层次模型中的第多少个层次,类型反射
2个简练的行使反射获取类型新闻的例证:

反射的框架结构应用

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

实际中的框架因为这么那样的原委,会有好奇的统一筹划,所以拘泥于①种设计情势是愚笨的,实战中要出头设计情势①起利用,局地设计有时只取设计方式中壹部分也得以。那样才能落到实处项指标量身定制。

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

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

       //定义二个得到反射内容的措施
       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()

代码中框架很简单,主要目标是促成一个代理,用于拍卖继承了CommandBase的类的代理。

                 //获取形式新闻
                 MethodInfo   myMethodInfo=type.GetMethods();

即,客户端,不论传来什么样的Command,只要它是后续自CommandBase的,那几个代理都会找到呼应的拍卖类,并推行处理,且重回结果。

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

为了更清楚的知情那段代码,我们能够参考上边这几个流程图。结合了图片在来看代码,框架结构就会更清楚。

                 //获取事件音信
                 EventInfo[] Myevents=type.GetEvents;
           }
      }
}
别的二种获得type对象的方法:
一、System.type  
参数为字符串类型,该字符串必须钦命项指标全体名称(包含其取名空间)
二、System.type 提供了三个实例方法:GetNestedType,GetNestedTypes
3、Syetem.Reflection.Assembly
类型提供的实例方法是:GetType,GetTypes,GetExporedTypes
肆、System.Reflection.Moudle
提供了这么些实例方法:GetType,GetTypes,FindTypes

美高梅开户网址 3

安装反光类型的分子:

以此简单的框架中,使用了三个概念,叫做约定优先原则,也称之为约定优于配备;喜欢概念的小伙伴能够活动百度。

反射类型的分子就是反射层次模型中最上面包车型大巴1层数据。大家能够通过type对象的GetMembers
方法获得一个项目标成员。如若大家运用的是不带参数的GetMembers,它只回去该品种的共用定义的静态变量和实例成员,大家也可以通过使用带参数的
GetMembers通过参数设置来回到钦定的门类成员。具体参数参考msdn
中system.reflection.bindingflags 枚举类型的详实表明。

框架中央银行使的三个约定如下:

例如:
//设置供给重返的品类的成员内容
美高梅开户网址,bindingFlags
bf=bingdingFlags.DeclaredOnly|bingdingFlags.Nonpublic|BingdingFlags.Public;
foreach (MemberInfo mi int t.getmembers(bf))
{
       writeline(mi.membertype)    //输出钦点的品种成员
}

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

经过反射创制项目的实例:

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

因此反射可以拿走程序集的种类,我们就能够依照取得的次第集类型来创制该项目新的实例,那也是眼前提到的在运作时创造对象达成晚绑定的效应
我们能够透过上边包车型地铁多少个艺术实现:
1、System.Activator
的CreateInstance方法。该措施重返新目的的引用。具体应用形式参见msdn
二、System.Activator 的createInstanceFrom
与上2个主意类似,但是需求钦命项目及其程序集
3、System.Appdomain
的方法:createInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap
四、System.type的InvokeMember实例方法:这些点子重临3个与传播参数相符的构造函数,并协会该品种。
5、System.reflection.constructinfo 的Invoke实例方法

实则概念正是供我们使用的,会用即可;学习的进程中,概念之类的术语,有个影象即可。

反射类型的接口:

PS:为了阅读方便,那其间的类都集中写在了贰个命名空间之下了,倘若有想行使那种设计情势的同室,请依照本身项目所需进行扩大。

假定你想要获得三个连串继承的富有接口集合,可以调用Type的FindInterfaces
GetInterface或然GetInterfaces。全体这么些方法只可以回去该类型直接接轨的接口,他们不会回到从3个接口继承下去的接口。要想回来接口的功底接口必须再度调用上述措施。


反射的属性:

如此那般,大家就由此反射达成了三个不胜简短的框架,通过运用那么些框架,会让代码变的愈来愈从简。

利用反射来调用类型也许触发方法,或许访问3个字段可能性质时clr
要求做更加多的工作:校验参数,检查权限等等,所以速度是不快的。所以尽大概不要采纳反射进行编制程序,对于打算编写三个动态构造类型(晚绑定)的应用程序,能够使用以下的三种方法开始展览代替:
一、通过类的后续关系。让该项目从一个编写翻译时可见的基础项目派生出来,在运作时生成该品种的1个实例,将对其的引用放到其基础项指标2个变量中,然后调用该基础项目的虚方法。
二、通过接口落成。在运维时,构建该类型的二个实例,将对其的引用放到其接口类型的三个变量中,然后调用该接口定义的虚方法。
三、通过信托达成。让该品种实现二个主意,其名称和原型都与三个在编写翻译时就已知的寄托符合。在运转时先构造该项目标实例,然后在用该办法的靶子及称谓构造出该信托的实例,接着通过委托调用你想要的秘诀。这么些点子相对与前方八个办法所作的行事要多一些,作用更低壹些。

而为了贯彻每一种模块的简练,反射也将会被封装在依次模块的最底层,所以,反射毫无疑问,就是框架设计的根基。

 

反射与特点

个体操作方案:

反射在系统中另1个根本应用正是与特点的重组使用。

源DLL类:

在有个别针锋相对复杂的系统中,难免会遭受有些处境,要讲对象中的一有个别属性清空,恐怕要赢得对象中的某个质量赋值。常常我们的兑现情势便是手写,叁个多少个的赋值。

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个属性的时候,这么做就值得了。

        }

既然如此能去掉属性的多寡,那么自然就能够为属性赋值。至于怎么样落到实处反射赋值,相信大家能够举一反3。

}

反射+天性最广泛的现象

}

反射+天性1起利用,最广泛的光景便是用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”);//得到形式

假诺只是1个实体,那么,多遍历两回也没影响。但,假诺是数十万的多少,那那多一回的遍历影响就大了。

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

而用反射+性格,就足以减小那一个额外遍历次数。

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

讲了这般多为何不给代码呢?

因为小编认为,将地点的内容全知晓的同学,应该能够说,已经框架启蒙了。那么,那一个反光+性格的DataTable转数据实体,要是能协调写出来,就终于框架入门了。所以,那里给大家留下了二个操演的长空。

留神,小编那边说的是框架,而不是架设。

框架与架构的不一致是这么的,框架是个名词,而架构是个动词。框架尽管很在行了,也遗落得足以架构的很好。那个大家依然要专注区分。

结语

看完了整篇小说,有的同学恐怕会有疑难,这么不熟悉的PropertyInfo和MethodInfo真的有人会用吗?都是Copy代码,然后使用呢。

答案是,当然有人能够理解应用。反射是架构师的入门基础,任何2个[能够实战]的架构师,都要求随时随地的能够手写出反射,因为优化框架是他俩的权力和权利。

据此,对此有所疑虑的同伴,可以努力演习了,将委托融入血液,是尖端软件工程师的功底,而将反射融入血液,就是架构师的底子了。

C#语法——元组类型

C#语法——泛型的有余选择

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

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

C#语法——事件,逐步边缘化的三弟。

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

我对C#的认知。


注:此小说为原创,欢迎转发,请在篇章页面显著地方给出此文链接!
若你认为那篇小说还可以,请点击下右下角的【推荐】,十二分谢谢!
只要您觉得那篇小说对你抱有协理,那就不要紧支付宝小小打赏一下啊。 

美高梅开户网址 4

 

发表评论

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

网站地图xml地图