架构师的入门基础

By admin in 4858.com on 2019年3月25日

前言

自家理解:

反射

反射

编制程序其实就是写代码,而写代码指标正是落到实处业务,所以,语法和框架也是为着促成工作而留存的。因而,不管多么巨大上的对象,实质上都以工作。

装配件:Assembly(程序集)

简介

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

  通过反射,即可对各种档次了如指掌,并且也得以由此反射成立、调用和做客对象,固然在编写翻译时不分明该目的的花色。

  程序集带有模块,模块包蕴类型,而项目涵盖成员。反射提供包装程序集、模块和项目标目的。能够行使反射动态地创建项目标实例,将项目绑定到存活对象,或从现有对象中拿走项目。

简介

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

  通过反射,即可对每一连串型了如指掌,并且也能够经过反射创立、调用和访问对象,即使在编写翻译时不鲜明该指标的项目。 

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

 

就此,作者认为并非把写代码上升到科学的莫斯中国科学技术大学学。上涨到艺术就能够了,因为艺术自己也从未惊人。。。。

晚绑定:早先时期绑定

优缺点

  优点:

  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 命名空间的类提供一种专用情势的反光,使你能够在运维时生成类型。

 

有趣味是好事,但就是知道了反光的精神,理解了反光是什么样规划的,你技术也没怎么质的转移。因为,技术水平最终如故要促成到应用上。

—————–原版的书文如下——–

反射的简练用法

  命名空间: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();

 

 

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

1、什么是反光
贰 、命名空间与装配件的涉嫌
叁 、运维期获得类型音信有怎样用
④ 、怎么着行使反射获取项目
伍 、怎么样根据项目来动态创建对象
六 、怎么样获得格局以及动态调用方法
7、动态创设委托

贰个科普的言传身教用法

  大家一初步上学三层架构的时候,都应有会自个儿跟着导师动手制作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个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():获取属性集合;

    (2)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的包必须依据目录结构来放置,命名空间则不需求。

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

 
     
装配件是.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#编制程序语言中,最常使用的是类和类中的函数和品质。正向调用的法门是,创立类,然后用类创制1个目的。接下来就能够用这几个目的调用类中的方法和天性了。

复制代码

而反射,正是相对于那种正向调用的留存。即,它是反向调用。

那七个装配件中都有N1和N2五个命名空间,而且各证明了四个类,那样是一点一滴可以的,然后大家在一个应用程序中引用装配件A,那么在那么些应用程序中,我们能收看N1下边包车型客车类为AC1和AC2,N2下边包车型客车类为AC3和AC4。
 
     
接着大家去掉对A的引用,加上对B的引用,那么大家在那些应用程序下能看到的N1上面包车型客车类成为了BC1和BC2,N2下边也一律。
 
     
假如我们同时引述那多个装配件,那么N1上边大家就能看出三个类:AC① 、AC② 、BC1和BC2。

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

 
     
到此地,大家能够知道1个概念了,命名空间只是说多美滋(Dumex)个门类是那多少个族的,比如有人是布依族、有人是水族;而装配件表美赞臣个品种住在何地,比如有人住在新加坡市、有人住在香岛;那么东京(Tokyo)有塔塔尔族人,也有独龙族人,北京有拉祜族人,也有哈萨克族人,那是不争持的。

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

 
     
上面大家说了,装配件是贰个门类居住的地点,那么在2个顺序中要利用叁个类,就亟须告诉编写翻译器这一个类住在何方,编写翻译器才能找到它,也正是说必须引用该装配件。
 
     
那么一旦在编写程序的时候,恐怕不明确这几个类在哪儿,仅仅只是知道它的名称,就不能够选用了呢?答案是足以,这便是反射了,正是在程序运营的时候提供该品种的地点,而去找到它。
有趣味的话,接着往下看呢。

会有那种题材的同室,先别着急,继续往下看,反射既然存在,就必将有存在的道理。

叁 、运维期获得类型音讯有啥样用
 
     
有人只怕难题,既然在付出时就能够写好代码,干嘛还放置运维期去做,不光繁琐,而且作用也受影响。
那正是个分化的标题了,就跟早绑定和晚绑定一样,应用到差别的地方。有的人反对晚绑定,理由是消耗功效,可是过几人在享用虚函数带来的功利的时侯还向来不察觉到她早已用上了晚绑定。这些题材说开去,不是三言两语能讲领会的,所以就点到完工了。
 
     
作者的观点是,晚绑定能够带来许多企划上的方便人民群众,合适的应用能够大大提升程序的复用性和灵活性,可是其余事物都有两面性,使用的时侯,需求再三衡量。

反射的根基运用

接着说,运转期获得类型音信到底有哪些用呢?
抑或举个例子来验证,很多软件开发者喜欢在祥和的软件中留下一些接口,别的人能够编写一些插件来扩大软件的效果,比如笔者有3个媒体播放器,小编梦想现在能够很便宜的恢弘识别的格式,那么小编声多美滋(Dumex)个接口:

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属性,这一个特性再次回到辅助的扩张名,另一个方法再次回到二个解码器的目标(那里作者假诺了二个Decoder的类,那些类提供把文件流解码的成效,扩充插件能够派生之),通过解码器对象自作者就足以分解文件流。
那么我显明全部的解码插件都不能够不派生3个解码器,并且达成那么些接口,在GetDecoder方法中回到解码器对象,并且将其品种的名称配置到自个儿的布置文件之中。
那样的话,小编就不供给在支付播放器的时侯知道以往增添的格式的门类,只须要从配置文件中获取今后有所解码器的项目名称,而动态的创建媒体格式的对象,将其更换为IMediaFormat接口来行使。

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

这便是一个反光的卓越应用。

在这之中字符串”Syntax.Kiba”是3个一心限定名。什么是完全限定名?完全限定名正是命名空间+类名。在反射的时候,须求大家传递完全限定名来分明到底要去哪个命名空间,找哪个类。

四 、怎么着运用反射获取项目
 
      首先大家来看怎么获得类型音信。
 
      获得类型音信有二种方法,一种是获取实例对象
 
     
这几个时侯作者只有是获取那么些实例对象,得到的办法恐怕是一个object的引用,恐怕是二个接口的引用,不过自己并不知道它的适宜品种,小编急需了然,那么就能够透过调用System.Object上证明的章程GetType来博取实例对象的门类对象,比如在有个别方法内,小编急需看清传递进入的参数是或不是达成了有个别接口,假诺达成了,则调用该接口的八个办法:

在代码中我们还足以见到,获取项指标法门有三种,一种是较复杂的,一种是回顾的。

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

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

复制代码

相互有怎么着分别呢?

别的一种得到项目标不二法门是通过Type.GetType以及Assembly.GetType方法,如:
 
            Type  t  =  Type.GetType(“System.String”);
 
     
必要注意的是,前边大家讲到了命名空间和装配件的关系,要摸索2个类,必须内定它所在的装配件,大概在已经取得的Assembly实例上边调用GetType。
 
     
本装配件中项目能够只写类型名称,另2个不及是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”);
 
        那样才足以,我们能够看下边这几个帖子:
4858.com, 
              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钦定了命名空间的名称,所以反射时,会去那么些命名空间里找类,那样是或不是就好驾驭了。

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

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

复制代码

一对同学恐怕会担心品质,会以为这么反射,会使程序变慢。

上边是3个简约的类,包蕴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#中贯彻事件的基础,有时候不可防止的要动态的创始委托,实际上委托也是一类别型:System.Delegate,全数的信托都以从那一个类派生的
 
     
System.Delegate提供了部分静态方法来动态制造二个寄托,比如1个寄托:

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的实例,接着定义了一个参数的Object数组,因为Kiba类下的函数PrintName只有一个参数,所以,我们只为那个Object数组添加四个指标[Kiba518]。

除此以外一篇关于反射的小说

末段,大家透过method.Invoke来调用那个函数,由于是反光,所以调用时,要求钦赐Kiba类的实例对象和入参。

—————原来的作品如下——————

那样,函数的反光就兑现了。

反射的概念:审查元数据并采访有关它的类型音信的能力。元数据(编写翻译以往的最大旨数据单元)就是一大堆的表,当编写翻译程序集或许模块时,编写翻译器会创制多个类定义表,多个字段定义表,和三个艺术定义表等。
         
System.reflection命名空间包含的多少个类,允许你反射(解析)这一个元数据表的代码   

3,属性反射

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定义和加载程序集,加载在先后集清单中列出模块,以及随后程序集中查找类型并创办该类型的实例。 
(2)使用Module了然包涵模块的次第集以及模块中的类等,还能取得在模块上定义的有着全局方法或别的特定的非全局方法。 
(3)使用ConstructorInfo精晓构造函数的名号、参数、访问修饰符(如pulic
或private)和贯彻详细消息(如abstract或virtual)等。使用Type的GetConstructors或
GetConstructor方法来调用特定的构造函数。 
(4)使用MethodInfo明白方法的称呼、重临类型、参数、访问修饰符(如pulic
或private)和促成详细消息(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的不二法门。 
(5)使用FiedInfo领悟字段的称谓、访问修饰符(如public或private)和兑现详细音讯(如static)等,并获取或设置字段值。 
(6)使用伊夫ntInfo驾驭事件的称谓、事件处理程序数据类型、自定义属性、注明类型和反光类型等,添加或移除事件处理程序。 
(7)使用PropertyInfo精晓属性的称谓、数据类型、注明类型、反射类型和只读或可写状态等,获取或安装属性值。 
(8)使用ParameterInfo驾驭参数的称谓、数据类型、是输入参数依旧出口参数,以及参数在点子签名中的地方等。
反射的层次模型:
4858.com 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;
    } 
}

反射的机能:
① 、能够利用反射动态地创建项指标实例,将品种绑定到存活对象,或从现有对象中拿走项目
② 、应用程序须要在运维时从有些特定的程序集中载入2个一定的品种,以便完成某些职务时得以用到反射。
③ 、反射重要选用与类库,那些类库要求知道2个类其余概念,以便提供愈多的效用。

如代码所示,首先大家定义了3个Kiba的靶子,并为Name赋值,然后我们由此GetPropertyValue方法,传递了Kiba对象和要获得值的质量名称。

利用中央:
一 、现实应用程序中很少有应用程序须要运用反射类型
② 、使用反射动态绑定供给就义质量
叁 、有些元数据新闻是无法因此反射获取的
四 、有些反射类型是专程为那么些clr
开发编写翻译器的付出使用的,所以你要发现到不是怀有的反光类型都以吻合各样人的。

GetPropertyValue函数里通过运用PropertyInfo达成了反光。

 

部分同学大概会以为,那些很鸡肋,既然已经收获指标,还反射做哪些,直接获取就能够了啊。

反射appDomain 的顺序集:

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

当你须求反射AppDomain 中蕴藏的具有程序集,示例如下:
static void Main
{
       //通过GetAssemblies 调用appDomain的具备程序集
       foreach (Assembly assem in
Appdomain.currentDomain.GetAssemblies())
      {
       //反射当前程序集的新闻
            reflector.ReflectOnAssembly(assem)
      }
}

反射的框架结构应用

证实:调用AppDomain 对象的GetAssemblies 方法
将赶回叁个由System.Reflection.Assembly成分组成的数组。

 框架编写的骨干指标之一,是统一系统秩序。那么哪些是系统秩序呢?

反射单个程序集:

 首先咱们看下系统的结缘,系统个一般是由子系统,程序集,类,函数那四有的构成。如下图所示。

上边的办法讲的是反射AppDomain的持有程序集,大家得以显示的调用在那之中的一个程序集,system.reflecton.assembly
类型提供了上边二种方法:
① 、Load 方法:极力推荐的一种艺术,Load
方法包罗贰个先后集标志并载入它,Load
将唤起CL奥迪Q3把政策应用到程序集上,先后在全局程序集缓冲区,应用程序基目录和个体路径上边查找该程序集,假使找不到该程序集系统抛出相当
二 、LoadFrom
方法:传递二个程序集文件的途径名(包罗扩充名),CLENCORE会载入您内定的这些程序集,传递的那一个参数无法包含别的有关版本号的新闻,区域性,和公钥消息,倘若在钦点路线找不到程序集抛出卓殊。
③ 、LoadWithPartialName:永远不要接纳这一个主意,因为应用程序不可能分明再在载入的次第集的本子。该办法的唯一用途是援助那多个在.Net框架的测试环节使用.net
框架提供的某种行为的客户,这一个方法将最后被丢掉不用。

4858.com 2

只顾:system.AppDomain 也提供了一种Load 方法,他和Assembly的静态Load
方法差别,AppDomain的load
方法是一种实例方法,再次来到的是3个对程序集的引用,Assembly的静态Load
方发将程序集按值封装发回给发出调用的AppDomain.尽量制止采纳AppDomain的load
方法

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

应用反射获取类型新闻:

很鲜明,任何的品类都设有双重的函数,恐怕成效相近的函数。而干净杜绝那种情状,显著是不容许的。那么我们不得不硬着头皮是安顿会防止双重成分的框架了。而反射,就是为此而留存的。

前方讲完了关于程序集的反射,下边在讲一下反光层次模型中的第6个层次,类型反射
二个总结的选择反射获取类型新闻的事例:

反射的框架结构应用

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

切切实实中的框架因为那样那样的由来,会有蹊跷的安排,所以拘泥于一种设计情势是高血压脑出血的,实战中要出头设计格局一起使用,局地设计有时只取设计形式中一部分也得以。那样才能促成项目的量身定制。

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

于是,那里只介绍一种实战的架构应用,一种采纳反射的框架基础结构。下边请框架基础代码。

       //定义2个获取反射内容的点子
       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
③ 、Syetem.Reflection.Assembly
类型提供的实例方法是:GetType,GetTypes,GetExporedTypes
④ 、System.Reflection.Moudle
提供了那些实例方法:GetType,GetTypes,FindTypes

4858.com 3

安装反光类型的分子:

其一简单的框架中,使用了贰个概念,叫做约定优先原则,也叫做约定优于配备;喜欢概念的同伙能够活动百度。

反射类型的分子固然反射层次模型中最上面包车型大巴一层数据。我们得以经过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)    //输出钦点的项目成员
}

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

因此反射创立项目标实例:

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

透过反射能够拿走程序集的连串,大家就可以依据取得的程序集类型来创立该类型新的实例,那也是前边提到的在运维时创制对象达成晚绑定的作用
作者们能够透过上面包车型客车多少个方法已毕:
一 、System.Activator
的CreateInstance方法。该形式重回新对象的引用。具体应用格局参见msdn
二 、System.Activator 的createInstanceFrom
与上3个方法类似,可是须求内定项目及其程序集
3、System.Appdomain
的方法:createInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap
肆 、System.type的InvokeMember实例方法:这些艺术重临贰个与传播参数相符的构造函数,并组织该品种。
⑤ 、System.reflection.constructinfo 的Invoke实例方法

实质上概念正是供我们使用的,会用即可;学习的长河中,概念之类的术语,有个影像即可。

反射类型的接口:

PS:为了阅读方便,这里面包车型地铁类都集中写在了三个命名空间之下了,若是有想选用那种设计格局的校友,请依照自身项目所需进行增添。

设若你想要获得四个品种继承的持有接口集合,能够调用Type的FindInterfaces
GetInterface恐怕GetInterfaces。全体那么些措施只可以重返该类型直接接轨的接口,他们不会回去从1个接口继承下去的接口。要想回到接口的基础接口必须另行调用上述方法。


反射的品质:

那般,我们就透过反射达成了1个要命简短的框架,通过选拔这些框架,会让代码变的更为从简。

使用反射来调用类型大概触发方法,可能访问叁个字段可能性质时clr
要求做更加多的行事:校验参数,检查权限等等,所以速度是很慢的。所以尽量不要接纳反射举办编制程序,对于打算编写三个动态构造类型(晚绑定)的应用程序,可以动用以下的二种艺术开始展览代替:
壹 、通过类的后续关系。让该项目从二个编写翻译时可见的底蕴项目派生出来,在运作时生成该类型的三个实例,将对其的引用放到其基础项指标一个变量中,然后调用该基础项目标虚方法。
二 、通过接口达成。在运营时,创设该项目标1个实例,将对其的引用放到其接口类型的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>”);

理所当然为了三个性能这么做不值得,但一旦2个对象有6一个天性的时候,这么做就值得了。

        }

既然如此能祛除属性的数额,那么自然就足以为属性赋值。至于怎么完结反射赋值,相信大家可以举一反三。

}

反射+天性最普遍的景色

}

反射+性格一起使用,最普遍的情景正是用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”);//得到情势

若是只是3个实体,那么,多遍历四次也没影响。但,假使是数80000的多寡,那那多几遍的遍历影响就大了。

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

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

反射机制对应设计情势中的策略情势。

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

因为自身以为,将下边包车型大巴情节全了解的同窗,应该可以说,已经框架启蒙了。那么,这些反光+性情的DataTable转数据实体,如若能团结写出来,就到底框架入门了。所以,那里给大家留下了一个练兵的空中。

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

框架与架构的界别是那般的,框架是个名词,而架构是个动词。框架就算很熟谙了,也有失得足以架构的很好。那么些我们依旧要留意区分。

结语

看完了整篇文章,有的同学或者会有疑问,这么生疏的PropertyInfo和MethodInfo真的有人会用吗?都是Copy代码,然后利用呢。

答案是,当然有人能够自如运用。反射是架构师的入门基础,任何2个[能够实战]的架构师,都须要随时四处的可以手写出反射,因为优化框架是他俩的权力和义务。

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

C#语法——元组类型

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

C#语法——await与async的不易打开药格局

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

C#语法——事件,慢慢边缘化的长兄。

C#语法——新闻,MVVM的大旨技术。

我对C#的认知。


注:此小说为原创,欢迎转发,请在小说页面分明地点给出此文链接!
若您觉得这篇文章尚可,请点击下右下角的【推荐】,卓殊谢谢!
若是你认为那篇文章对您拥有帮助,那就不要紧支付宝小小打赏一下吗。 

4858.com 4

 

发表评论

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

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有