【亚洲必赢官网】架构师的入门基础

前言

笔者驾驭:

反射

反射

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

装配件:Assembly(程序集)

简介

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

  通过反射,即可对每1种档次了如指掌,并且也得以通过反射创制、调用和走访对象,就算在编写翻译时不鲜明该指标的项目。

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

简介

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

  通过反射,即可对每壹种档次了如指掌,并且也得以经过反射创制、调用和做客对象,即使在编写翻译时不明确该指标的体系。 

  程序集带有模块,模块包涵类型,而项目涵盖成员。反射提供包装程序集、模块和体系的目的。能够利用反射动态地创制项目的实例,将品种绑定到现有对象,或从现有对象中赢得项目。

 

之所以,笔者认为并非把写代码上涨到科学的万丈。上升到点子就足以了,因为艺术本人也未有中度。。。。

晚绑定:后期绑定

优缺点

  优点:

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

 

 

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

一、
什么是反光
二、
命名空间与装配件的关联
三、
运维期获得类型消息有哪些用
4、
怎样使用反射获取项目
5、
怎么着依照项目来动态创制对象
陆、
怎样取得方式以及动态调用方法
柒、
动态成立委托

三个普遍的演示用法

  我们一开首上学3层架构的时候,都应该会自身接着导师动手制作1个SqlHelper
的吗,那里笔者截取三个经过反射读取数据库数据并填充到3个对象的天性上,通过巡回遍历,最生平成1个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):属性赋值,选取相应的对象举办赋值。


反骨仔

微软官方文书档案

 一个科学普及的言传身教用法

  大家一起先上学叁层架构的时候,都应有会本身随后导师动手营造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(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:可写属性;

    (三)propertyInfo.SetValue(entity,
val):属性赋值,选取相应的对象进行赋值。

 

 


【博主】反骨仔

【原文】 

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

 

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

一、什么是反光
 
      Reflection,普通话翻译为反射。
 
     
那是.Net中赢得运营时类型音讯的艺术,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编制程序的方法,让程序员能够在先后运维期获得那多少个组成都部队分的相干新闻,例如:


 
     
Assembly类能够赢得正在运转的装配件新闻,也足以动态的加载装配件,以及在装配件中寻觅类型消息,并创办该类型的实例。
Type类能够获得对象的类型消息,此音信包括对象的兼具因素:方法、构造器、属性等等,通过Type类能够赢得这几个因素的音信,并且调用之。
MethodInfo包蕴方法的信息,通过那个类能够获得方法的称谓、参数、再次来到值等,并且能够调用之。
如此,还有FieldInfo、伊夫ntInfo等等,那些类都包括在System.Reflection命名空间下。

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

2、命名空间与装配件的关系
 
     
很几个人对那几个概念恐怕依旧很不明晰,对于合格的.Net程序员,有供给对这一点展开辟谣。
 
      命名空间类似与Java的包,但又不完全1样,因为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#编制程序语言中,最常使用的是类和类中的函数和质量。正向调用的方法是,制造类,然后用类成立3个对象。接下来就能够用那一个目的调用类中的方法和性质了。

复制代码

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

那三个装配件中都有N一和N二五个命名空间,而且各注解了七个类,那样是截然能够的,然后大家在一个应用程序中引用装配件A,那么在这么些应用程序中,大家能收看N1下边包车型客车类为AC一和AC二,N贰下边的类为AC3和AC四。
 
     
接着大家去掉对A的引用,加上对B的引用,那么我们在那些应用程序下能看到的N一下边包车型客车类成为了BC一和BC二,N2上边也一如既往。
 
     
若是大家还要引述那七个装配件,那么N一上面大家就能见到八个类:AC一、AC二、BC一和BC二。

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

 
     
到此处,大家得以知道3个定义了,命名空间只是表明1(Wissu)个连串是那贰个族的,比如有人是撒拉族、有人是京族;而装配件表爱他美(Karicare)个品类住在何地,比如有人住在京城、有人住在香港(Hong Kong);那么香水之都有乌孜Buick族人,也有水族人,新加坡有朝鲜族人,也有景颇族人,那是不争辨的。

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

 
     
下面大家说了,装配件是2个档次居住的地点,那么在二个主次中要使用三个类,就必须告诉编写翻译器那几个类住在何处,编译器才能找到它,也正是说必须引用该装配件。
 
     
那么只要在编写程序的时候,只怕不分明那个类在何地,仅仅只是知道它的名号,就不可能动用了呢?答案是足以,这正是反光了,正是在程序运转的时候提供该项指标地址,而去找到它。
有趣味的话,接着往下看吗。

会有那种难点的同学,先别着急,继续往下看,反射既然存在,就自然有存在的道理。

叁、运维期获得类型信息有如何用
 
     
有人只怕难题,既然在付出时就可见写好代码,干嘛还内置运营期去做,不光繁琐,而且作用也受影响。
那正是个例外的题材了,就跟早绑定和晚绑定一样,应用到分化的场子。有的人反对晚绑定,理由是消耗功用,但是不少人在分享虚函数带来的便宜的时侯还尚未察觉到她已经用上了晚绑定。这些标题说开去,不是三言两语能讲领会的,所以就点到截至了。
 
     
小编的见识是,晚绑定能够推动许多企划上的惠及,合适的施用能够大大进步程序的复用性和灵活性,可是任何事物都有两面性,使用的时侯,必要再叁衡量。

反射的底子运用

【亚洲必赢官网】架构师的入门基础。随后说,运营期获得类型音讯到底有何用吗?
恐怕举个例子来注明,很多软件开发者喜欢在大团结的软件中留下1些接口,别的人能够编写壹些插件来扩充软件的效应,比如笔者有一个媒体播放器,作者希望未来能够很有利的壮大识其他格式,那么笔者声澳优(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的类,那个类提供把公文流解码的效益,扩大插件能够派生之),通过解码器对象自笔者就足以表明文件流。
那么本人鲜明具有的解码插件都无法不派生贰个解码器,并且完结那一个接口,在GetDecoder方法中回到解码器对象,并且将其类别的名目配置到自家的布局文件之中。
那样的话,笔者就不需求在付出播放器的时侯知道今后增加的格式的门类,只须求从配置文件中收获今后有所解码器的品种名称,而动态的创造媒体格式的目的,将其更换为IMediaFormat接口来行使。

在代码中我们看到,反射时传递了字符串”Syntax.Kiba”,然后通过分析字符串,获取到了该字符串对应的类的项目,最终再借助Activator来扶助成立类的实例。

那正是一个反光的第一名应用。

个中字符串”Syntax.Kiba”是2个一心限定名。什么是一心限定名?完全限定名便是命名空间+类名。在反射的时候,须求大家传递完全限定名来鲜明毕竟要去哪个命名空间,找哪位类。

四、怎样使用反射获取项目
 
      首先大家来看什么获取类型音信。
 
      获得类型新闻有二种办法,一种是得到实例对象
 
     
这几个时侯小编偏偏是获得那几个实例对象,获得的不2秘籍也许是1个object的引用,可能是叁个接口的引用,可是本身并不知道它的熨帖品种,笔者索要掌握,那么就足以因此调用System.Object上注解的办法GetType来赢得实例对象的类别对象,比如在某些方法内,小编索要看清传递进入的参数是或不是落到实处了有些接口,借使达成了,则调用该接口的三个措施:

在代码中大家还是能看来,获取项目标方法有三种,1种是较复杂的,一种是大约的。

  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”);
 
     
须要专注的是,前边大家讲到了命名空间和装配件的涉及,要摸索三个类,必须钦定它所在的装配件,恐怕在早就收获的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钦点了命名空间的名称,所以反射时,会去这么些命名空间里找类,那样是还是不是就好了解了。

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

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。调用格局如下:

把参数依据顺序放入3个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的法子,1个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个类名,那么速度就会变慢。因为它要遍历全体的命名空间,去找这几个类。

性格与方式的调用安顺小异,我们也得以参照MSDN

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

柒、动态创造委托
 
      委托是C#中贯彻事件的根基,有时候不可幸免的要动态的成立委托,实际上委托也是1种档次:System.Delegate,全体的委托都是从那么些类派生的
 
     
System.Delegate提供了1部分静态方法来动态创设1个信托,比如一个信托:

二,函数反射

  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唯有1个参数,所以,大家只为这些Object数组添加一个对象[Kiba518]。

除此以外壹篇关于反射的稿子

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

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

诸如此类,函数的反光就落实了。

反射的概念:审查元数据并征集有关它的类型新闻的能力。元数据(编写翻译今后的最基本数据单元)正是一大堆的表,当编写翻译程序集只怕模块时,编写翻译器会成立1个类定义表,多个字段定义表,和叁个办法定义表等。
         
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
以下是下面多少个类的应用格局:
(一)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及之后程序集中查找类型并创办该项目标实例。 
(二)使用Module明白包涵模块的程序集以及模块中的类等,还足以博得在模块上定义的享有全局方法或别的特定的非全局方法。 
(三)使用ConstructorInfo精晓构造函数的称号、参数、访问修饰符(如pulic
或private)和促成详细音讯(如abstract或virtual)等。使用Type的GetConstructors或
GetConstructor方法来调用特定的构造函数。 
(4)使用MethodInfo驾驭方法的称号、再次回到类型、参数、访问修饰符(如pulic
或private)和兑现详细音讯(如abstract或virtual)等。使用Type的GetMethods或GetMethod方法来调用特定的艺术。 
(伍)使用FiedInfo领会字段的称呼、访问修饰符(如public或private)和贯彻详细消息(如static)等,并拿走或安装字段值。 
(陆)使用伊夫ntInfo通晓事件的称呼、事件处理程序数据类型、自定义属性、证明类型和反光类型等,添加或移除事件处理程序。 
(7)使用PropertyInfo驾驭属性的称呼、数据类型、注脚类型、反射类型和只读或可写状态等,获取或设置属性值。 
(8)使用ParameterInfo理解参数的称号、数据类型、是输入参数如故出口参数,以及参数在方式签名中的地方等。
反射的层次模型:
亚洲必赢官网 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、反射主要行使与类库,那么些类库须要精通多个体系的概念,以便提供愈来愈多的功能。

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

应用大旨:
壹、现实应用程序中很少有应用程序要求动用反射类型
二、使用反射动态绑定需求就义质量
三、某些元数据新闻是不可能透过反射获取的
4、有个别反射类型是专程为这些clr
开发编写翻译器的付出使用的,所以您要发现到不是持有的反光类型都以符合种种人的。

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

 

1对同学大概会以为,这么些很鸡肋,既然已经收获指标,还反射做什么样,直接得到就能够了啊。

反射appDomain 的程序集:

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

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

反射的架构应用

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

 框架编写的主导指标之1,是联合系统秩序。那么什么样是系统秩序呢?

反射单个程序集:

 首先我们看下系统的3结合,系统个常见是由子系统,程序集,类,函数那肆部分构成。如下图所示。

上边的格局讲的是反射AppDomain的装有程序集,大家得以体现的调用当中的多少个程序集,system.reflecton.assembly
类型提供了上边两种方法:
一、Load 方法:极力推荐的壹种办法,Load
方法包蕴一个先后集标志并载入它,Load
将唤起CLPRADO把政策应用到程序集上,先后在全局程序集缓冲区,应用程序基目录和私家路径上面查找该程序集,若是找不到该程序集系统抛出非凡
2、LoadFrom
方法:传递二个主次集文件的门路名(包蕴扩充名),CLBMWX3会载入您钦定的那一个程序集,传递的那几个参数不能够包罗其余有关版本号的音讯,区域性,和公钥新闻,即使在钦赐路线找不到程序集抛出拾分。
叁、LoadWithPartialName:永远不要采纳那么些措施,因为应用程序不可能明确再在载入的程序集的版本。该情势的绝无仅有用途是支援那一个在.Net框架的测试环节使用.net
框架提供的某种行为的客户,那一个法子将最后被撇下不用。

亚洲必赢官网 2

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

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

行使反射获取类型新闻:

很引人侧目,任何的项目都设有重新的函数,可能作用周边的函数。而干净杜绝那种状态,显著是不容许的。那么大家不得不硬着头皮是设计会防止重新成分的框架了。而反射,就是为此而存在的。

前方讲完了有关程序集的反射,下边在讲一下反光层次模型中的第三个层次,类型反射
1个简短的行使反射获取类型音讯的例子:

反射的架构应用

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

具体中的框架因为那样那样的原故,会有蹊跷的设计,所以拘泥于1种设计形式是工巧的,实战中要出头设计情势壹起行使,局地设计有时只取设计情势中1部分也能够。那样才能落到实处项目标量身定制。

             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
叁、Syetem.Reflection.Assembly
类型提供的实例方法是:GetType,GetTypes,GetExporedTypes
肆、System.Reflection.Moudle
提供了那些实例方法:GetType,GetTypes,FindTypes

亚洲必赢官网 3

设置反光类型的积极分子:

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

反射类型的分子就是反射层次模型中最下面包车型客车1层数据。大家能够透过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
与上1个办法类似,然而要求内定项目及其程序集
3、System.Appdomain
的方法:createInstance,CreateInstanceAndUnwrap,CreateInstranceFrom和CreateInstraceFromAndUnwrap
4、System.type的InvokeMember实例方法:那么些情势重返几个与传播参数相符的构造函数,并协会该类型。
五、System.reflection.constructinfo 的Invoke实例方法

实质上概念便是供大家使用的,会用即可;学习的进程中,概念之类的术语,有个影像即可。

反射类型的接口:

PS:为了阅读方便,那中间的类都集中写在了二个命名空间之下了,假使有想行使那种设计情势的校友,请依照自身项目所需实行扩展。

若果你想要得到3个门类继承的有着接口集合,能够调用Type的FindInterfaces
GetInterface或许GetInterfaces。全数那几个措施只好回去该项目直接接轨的接口,他们不会回到从二个接口继承下去的接口。要想再次来到接口的基础接口必须重新调用上述办法。


反射的品质:

这么,大家就由此反射达成了一个尤其简便的框架,通过应用那些框架,会让代码变的尤为简洁。

动用反射来调用类型可能触发方法,或然访问1个字段可能性质时clr
需求做越多的劳作:校验参数,检查权限等等,所以速度是很慢的。所以尽大概不要使用反射举行编制程序,对于打算编写三个动态构造类型(晚绑定)的应用程序,能够选择以下的二种方法展开代替:
一、通过类的接轨关系。让该品种从二个编写翻译时可见的底子项目派生出来,在运行时生成该类型的一个实例,将对其的引用放到其基础项指标二个变量中,然后调用该基础项指标虚方法。
二、通过接口达成。在运行时,创设该项目标2个实例,将对其的引用放到其接口类型的贰个变量中,然后调用该接口定义的虚方法。
三、通过信托完毕。让该品种达成多个方法,其名称和原型都与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个目的有6九性格格的时候,这么做就值得了。

        }

既然能解除属性的数额,那么自然就能够为属性赋值。至于何以落到实处反射赋值,相信我们可以举壹反三。

}

反射+本性最广泛的气象

}

反射+本性一起行使,最广泛的风貌正是用ADO.NET从数据库查询出DataTable的多寡,然后将DataTable的多寡转换来Model实体类型。

//调用代码

咱俩在开发中,为了让实体特别充血,往往会对数据实体扩充1些性子和措施。(什么是充血?充血正是充血模型,有趣味的同窗能够自行百度问询下,不难说正是为实体加属性和方法。)

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#的认知。


注:此文章为原创,欢迎转载,请在篇章页面显然地点给出此文链接!
若你认为那篇小说还可以,请点击下右下角的【推荐】,分外感激!
假如你觉得那篇文章对您拥有扶助,这就不要紧支付宝小小打赏一下吗。 

亚洲必赢官网 4

 

网站地图xml地图