澳门至尊网站-首页

您的位置:澳门至尊网站 > 搜索引擎 > 架构师的入门基础

架构师的入门基础

2019-10-22 02:54

前言

反射

编程其实便是写代码,而写代码目标正是落到实处业务,所以,语法和框架也是为了贯彻工作而留存的。由此,不管多么宏大上的对象,实质上都以事情。

简介

  反射是 .NET中的首要机制,通过反射,能够在运作时收获程序或程序聚集类型(包括class、struct、delegate、interface 和 enum 等)的分子和成员的消息。

  通过反射,就能够对每大器晚成类别型如数家珍,何况也足以经过反射创造、调用和做客对象,纵然在编写翻译时不明确该对象的档案的次序。

  程序集带有模块,模块包括类型,而项目包蕴成员。反射提供包装程序集、模块和花色的靶子。还行反射动态地创造项目标实例,将品种绑定到现成对象,或从现成对象中赢得项目。

之所以,笔者感觉毫无把写代码回涨到精确的莫斯中国科学技术大学学。上升到形式就能够了,因为艺术本身也远非惊人。。。。

优缺点

  优点:

  1. 升高了前后相继的圆滑和扩张性;
  2. 跌落耦合性;
  3. 它同意程序成立和决定其余类的指标,无需提前硬编码目标类。

  缺点:

  1. 性情:使用反射基本上是意气风发种解释操作,从理论上讲使用反射远慢于直接代码;
  2. 可读性收缩。

软件设计存在过度设计,语法和框架的了然,也设有过度领会。例如,反编写翻译下,看看反射是怎么贯彻的。。。

反射的类型成员音信

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

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

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

  • FieldInfo:字段成员音讯(如名称、访谈修饰符)。

  • EventInfo:事件成员音信(如名称、事件管理程序的数据类型、自定义本性、证明类型以致事件的反射的档案的次序)。

  • PropertyInfo:属性成员新闻(如名称、数据类型、注解类型,反射的体系和总体性的只读或可写状态),并收获或安装属性值。

  • ParameterInfo:参数成员新闻(如参数名、数据类型以至参数在艺术签字中的地方等)。

  • CustomAttributeData:自定义性子信息。

  System.Reflection.Emit命名空间的类提供风流倜傥种专用方式的反射,使您可以知道在运作时生成类型。

有野趣是好事,但尽管知道了反光的本来面目,理解了反光是何许盘算的,你技能也没怎么质的更换。因为,本事水平最终照旧要落到实处到利用上。

反射的简练用法

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

  常见的猎取 Type 对象的用法:

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

在诸如,过度的言情代码品质,也不一定是龙马精神件好事,因为,[大多数]情形下,硬件比技术员平价多了。。。(注意这里指的是代码不是算法和数据库质量)

三个广泛的演示用法

  大家风流倜傥开头上学三层架构的时候,都应有会协和随后导师动手构建一个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):属性赋值,选择相应的指标举行赋值。


反骨仔

微软官方文书档案

因而,所有事,过度了,总不是好事。


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

反射是架设师必会的基础,因为别的三个被规划出来的框架,都要接收反射。

反射也是最掩没的语法,因为反射写出来后,经常它会被一直封装,然后调用者就只担负利用,不再关怀她的涉笔成趣得以达成。

那与它的特色有关,因为反射正是为了削减代码冗余而存在的,所以,看不见特不荒谬。

反射的定义

合法概念:反射提供了包装程序集、模块和体系的靶子(Type 类型)。能够利用反射动态创制类型的实例,将品种绑定到存活对象,或从现成对象获得项目并调用其艺术或访谈其字段和特性。假使代码中使用了品质,能够应用反射对它们举办访问。

看不懂?不妨,我们把它翻译成年人类可通晓的言语。

C#编制程序语言中,最常使用的是类和类中的函数和性情。正向调用的方法是,创立类,然后用类创立二个指标。接下来就能够用这些指标调用类中的方法和性格了。

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

反射能够透过类名的字符串来创设类,能够因此函数名的字符串和属性名的字符串,来调用类下的函数和总体性。

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

会有这种主题材料的同学,先别发急,继续往下看,反射既然存在,就势必有存在的道理。

反射的根基运用

1,类反射

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

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

在代码中我们见到,反射时传递了字符串"Syntax.Kiba",然后通过深入分析字符串,获取到了该字符串对应的类的连串,最终再依靠Activator来提携创设类的实例。

此中字符串"Syntax.Kiba"是四个一心限定名。什么是完全限定名?完全限定名正是命名空间+类名。在反射的时候,需要大家传递完全限定名来明确毕竟要去哪个命名空间,找哪个类。

在代码中大家还足以看出,获取项目标法子有三种,豆蔻梢头种是较复杂的,神采奕奕种是粗略的。

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

两岸有哪些分别呢?

区分是,用Type间接深入分析,只可以解析当前命名空间下的类。假设此类存在于引用的DLL中,就剖判不了。

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

[Assembly.Load钦点了先后集名]那句话不好驾驭?

不妨,换个表明,Assembly.Load钦命了命名空间的称呼,所以反射时,会去那么些命名空间里找类,那样是否就好理解了。

Assembly

Assembly的留存让反射变得极其灵巧,在这之中Assembly.Load不独有能够导入我们引进的程序集(或命名空间)。

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

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

Assembly导入了前后相继集后,还可以够不依赖Activator来增加接济,自个儿就足以创制类。如下:

Assembly assembly = Assembly.Load("Syntax");
Kiba kiba = (Kiba)assembly.CreateInstance("Syntax.Kiba");

黄金年代对同学大概会忧郁质量,会感觉这么反射,会使程序变慢。

有这种主张的同窗,其实您早正是在过度理解语法了。这种地点的代码质量其实是能够不用关爱的。

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

答案是如此的,如果你是行使完全限定名来反射,速度就是千篇龙腾虎跃律的。借使是反射时,只写了一个类名,那么速度就能变慢。因为它要遍历全体的命名空间,去找那几个类。

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

2,函数反射

函数的反光应用关键是应用类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);
    }
}

局地同室第黄金时代当即上去也许会有一点不适应,因为类似非常多类都以大家不平日用的。那也不可能,因为那是三个晋级的历程,必须经历从素不相识到熟知。当您熟知了如此的代码后,就意味着你的工夫水平又提升了一个阶梯。

下边讲授一些这么些代码。

率先大家导入了命名空间,接着大家获得了该命名空间下Kiba那一个类的等级次序;接下去我们经过这些类型来收获钦定名称的函数。

下一场我们因此Assembly创立了一个Kiba的实例,接着定义了多少个参数的Object数组,因为Kiba类下的函数PrintName唯有一个参数,所以,大家只为这一个Object数组增添四个指标[Kiba518]。

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

与此相类似,函数的反射就落到实处了。

3,属性反射

性子反射是用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;
    } 
}

如代码所示,首先大家定义了叁个Kiba的对象,并为Name赋值,然后大家通过GetPropertyValue方法,传递了Kiba对象和要博取值的性情名称。

GetPropertyValue函数里通过使用PropertyInfo实现了反光。

后生可畏部分同学大概会以为,这些很鸡肋,既然已经获得目的,还反射做如何,直接获得就能够了呀。

别发急,大家接下去一齐看反射的架构应用。

反射的架构应用

 框架编写的主导目标之热气腾腾,是联合系统秩序。那么哪些是系统秩序呢?

 首先大家看下系统的整合,系统个普通是由子系统,程序集,类,函数那四片段构成。如下图所示。

图片 1

既然如此系统由子系统,程序集,类,函数那多少个基础成分构成,那么系统秩序,自然指的正是这多个因素的秩序。而那八个要素最宫外孕生秩序的正是函数了。

很显然,任何的连串都存在重新的函数,也许功用类似的函数。而根本杜绝这种景况,鲜明是不容许的。那么大家不得不硬着头皮是规划会幸免再一次成分的框架了。而反射,就是为此而存在的。

反射的架构应用

实际中的框架因为那样那样的原由,会有好奇的筹划,所以拘泥于后生可畏种设计格局是愚拙的,实战中要出头设计格局一同利用,局地设计一时只取设计格局中大器晚成部分也足以。那样本领兑现项目的量身定制。

故而,这里只介绍后生可畏种实战的架构应用,大器晚成种采用反射的框架基础结构。上边请框架基础代码。

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

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

即,客商端,无论传来什么样的Command,只要它是一连自CommandBase的,那几个代理都会找到呼应的拍卖类,并实施管理,且重临结果。

为了更清晰的了然这段代码,大家得以仿效上面这几个流程图。结合了图片在来看代码,架构就能更鲜明。

图片 2

以此大约的框架中,使用了一个定义,叫做约定优先原则,也称为约定优于配备;喜欢概念的同伴能够自动百度。

框架中运用的五个约定如下:

率先个是,管理Command的类必得后缀名是Command的类名+Handler结尾。

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

实质上概念正是供我们使用的,会用就可以;学习的经过中,概念之类的术语,有个印象就可以。

PS:为了阅读方便,这几个中的类都集中写在了一个命名空间之下了,如若有想接纳这种设计形式的同班,请依照自个儿项目所需举办增加。


如此,大家就通过反射完毕了三个极其简短的框架,通过动用这几个框架,会让代码变的越发简洁。

而为了完毕各个模块的精简,反射也将会被封装在各样模块的最底层,所以,反射千真万确,便是框架设计的根基。

反射与特色

反射在系统中另三个器重应用正是与特色的重新整合使用。

在方兴未艾部分针锋相投复杂的种类中,难免会蒙受一些光景,要讲对象中的活龙活现部分属性清空,或许要拿走对象中的有些质量赋值。日常大家的落到实处情势正是手写,二个叁个的赋值。

而接纳反射并结成特性,完全能够简化这种复杂操作的代码量。

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

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

自然为了一个属性这么做不值得,但假若一个对象有62个本性的时候,这么做就值得了。

既是能清除属性的数码,那么自然就足以为属性赋值。至于何以贯彻反射赋值,相信大家可以触类旁通。

反射+天性最分布的现象

反射+性情一同行使,最常见的风貌正是用ADO.NET从数据库查询出DataTable的数量,然后将DataTable的数目转变到Model实体类型。

小编们在开荒中,为了让实体越发充血,往往会对数据实体扩张部分属性和艺术。(什么是充血?充血正是充血模型,有乐趣的同桌能够活动百度问询下,轻松说就是为实体加属性和措施。)

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

龙腾虎跃旦只是三个实体,那么,多遍历两回也没影响。但,如若是数十万的数额,那那多四回的遍历影响就大了。

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

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

因为笔者觉着,将地方的内容全驾驭的同桌,应该能够说,已经框架启蒙了。那么,这些反光+特性的DataTable转数据实体,借使能本身写出来,固然是框架入门了。所以,这里给我们留下了一个演习的空间。

专心,小编那边说的是框架,并不是架设。

框架与架构的界别是那般的,框架是个名词,而架构是个动词。框架纵然很谙习了,也遗落得足以架构的很好。这么些大家仍旧要注意区分。

结语

看完了整篇小说,有的同学可能会有问号,这么面生的PropertyInfo和MethodInfo真的有人会用吗?都是Copy代码,然后利用呢。

答案是,当然有人能够自如运用。反射是架构师的入门基础,任何一个[能够实战]的架构师,都亟待时时到处的能够手写出反射,因为优化框架是他们的权利。

所以,对此负有疑心的同伴,能够全力以赴演练了,将委托融入血液,是尖端软件程序猿的底蕴,而将反射融合血液,正是架构师的根底了。

C#语法——元组类型

C#语法——泛型的有余行使

C#语法——await与async的不错张开药方式

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

C#语法——事件,慢慢边缘化的小叔子。

C#语法——新闻,MVVM的核心才具。

我对C#的认知。


注:此小说为原创,招待转发,请在篇章页面显著地方给出此文链接!
若你认为那篇文章还不易,请点击下右下角的【推荐】,非常谢谢!
黄金年代经你感到那篇文章对你具备利于,那就不要紧支付宝小小打赏一下呢。 

图片 3

 

本文由澳门至尊网站发布于搜索引擎,转载请注明出处:架构师的入门基础

关键词: