利用Emit达成给实体赋值分分快三计划

作者:编程技术

 

.NET中的反射风度翩翩例

当大家相比多个引用类型的变量是不是等于时,大家比较的是那三个变量所指向的是还是不是堆上的同三个实例(内部存款和储蓄器地址是或不是意气风发律)。而当大家相比三个结构体是不是等于时,咋办吗?因为变量自个儿包罗了协会体全体的字段(数据),所以在可比时,就要求对多少个结构体的字段进行逐项的一定的可比,看看每种字段的值是还是不是都极其,固然别的一个字段的值不等,就重返false。

实质上,实践那样的一个相比较并不必要大家和睦编辑代码,Microsoft已经为大家提供了贯彻的诀要:全数的值类型继承自System.ValueType,ValueType和持有的类型都卫冕自System.Object,Object提供了一个Equals()方法,用来判断八个对象是否等于。但是ValueType覆盖了Object的Equals()方法。当大家相比较四个值类型变量是不是等于时,能够调用世襲自ValueType类型的Equals()方法。以此复写的章程内部采取了反光,获得值类型全数的字段,然后实行相比。

 

反射有如何应用处景?

在广大时候反射是唯大器晚成的接纳

当大家须要动态加载有个别程序集(并非在程序开始时就加载卡塔尔国,必要动用反射。但反射最习以为常的气象是,对象是不解的,或缘于外界,或是二个通用的模子举例ORM框架,其针对性的目的能够是其余类型。举例:对象的种类化和反种类化。

为啥大家会筛选接纳反射?因为我们一贯不章程在编写翻译期通过静态绑定的方法来规定我们要调用的靶子。举例二个ORM框架,它要直面的是通用的模子,这时候无论方法也好属性也罢都是随应用项景而更动的,这种完全要求动态绑定的光景下自然要求运用反射。还比方插件系统,在一丝一毫不知底外部插件毕竟是何等东西的境况下,是确定不可能在编写翻译期鲜明的,因而只可以动用动态加载举办加载,然后经过反射探查其方法,并反射调用方法。 

运维结果如下图所示:

加载程序集(最二〇二〇时期绑定卡塔尔

先写叁个用以演示的项目:

public class Class1
    {
        public int aPublicField;
        private int aPrivateField;
        public int aPublicProperty { get; set; }
        private int aPrivateProperty { get; set; }

        public event EventHandler aEvent;

        //Ctor
        public Class1()
        {

        }

        public void HelloWorld()
        {
            Console.WriteLine("Hello world!");
        }

        public int Add(int a, int b)
        {
            return a   b;
        }
    }

早先时代绑定就是观念的格局:CLLX570在运营代码在此之前,扫描任何或者的连串,然后建设构造项目对象。最后一段时期绑定则相反,在运作时才确立项目对象。我们能够用System.Reflection中的Assembly类型动态加载程序集。(在急需的时候加载一个外表的程序集卡塔尔

假诺能够接收前期绑定,那么自然是中期绑定越来越好。因为CLTiguan在前期绑定期会检查项目是不是错误,实际不是在运作时才看清。

当试图利用后期绑依期,你是在援引一个在运维时未有加载的次序集。你供给先选拔Assembly.Load或LoadFrom方法找到程序集,然后你能够选择GetType得到该程序集的一个类型,最终,使用Activator.CreateInstance(你获得的类型对象卡塔 尔(英语:State of Qatar)创制该项目标贰个实例。

注意,那样创建的档案的次序实例是Object类型。(C# 4引进了动态类型之后,也能够用dynamic修饰那体系型的实例卡塔尔那么些类型对象的章程都不可以见到,一旦要采纳它的方式,只可以利用反射(比方利用GetMethods得到方式音讯,然后再Invoke卡塔 尔(英语:State of Qatar)。这是反射最普遍的运用处景。

本来,你不应有引用该程序集,不然,就成为最早绑定了。假如大家将方面包车型地铁躬体力行类型放在贰个class library中,然后,在另三个工程中打开早先时期绑定。那时大家不将该class library参预参照他事他说加以考查,而是选用反射的办法,大家策画拿走演示类,并成立二个实例,就象是大家投入了参照他事他说加以调查同样。

class Program
    {
        static void Main(string[] args)
        {
            Assembly a = null;

            try
            {
                a = Assembly.LoadFile(@"C:CSharpBasicReflectionDemoClassbinDebugReflectionDemoClass.dll");
            }
            catch (Exception ex)
            {
                //Ignore
            }

            if (a != null)
            {
                CreateUsingLateBinding(a);
            }
            Console.ReadLine();
        }

        static void CreateUsingLateBinding(Assembly asm)
        {
            try
            {
                // 获得实例类型,ReflectionDemoClass是命名空间的名字
                Type t = asm.GetType("ReflectionDemoClass.Class1");

                // 晚期绑定建立一个Class1类型的实例
                object obj = Activator.CreateInstance(miniVan);

                // 获得一个方法
                MethodInfo mi = t.GetMethod("HelloWorld");

                // 方法的反射执行(没有参数)
                mi.Invoke(obj, null);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }

动用动态类型能够简化后期绑定。

 

分分快三计划 1

拿到类型成员

获取类型成员要求先具有叁个门类。大家常常经过typeof(那是GetType方法的简写卡塔尔得到类型对象,然后再使用各个法子赢得类型的分子:

GetMembers:暗中认可只拿到公开的成员,包含自个儿和品种全部父类的公然成员。成员包蕴字段,属性,方法,构造函数等。若想博得一定的成员,可以传入BindingFlags枚举,能够流传两个枚举值:

  • Static:静态成员
  • Instance:实例成员
  • Public:公开成员
  • NonPublic:非公开成员
  • DeclaredOnly:只回去本人类型内的成员,不回来父类的分子

BindingFlags枚举被Flags本性修饰,Flags个性非常符合这体系型的枚举:每便传入的成员数是不定的。从概念上得以看来,种种枚举对应贰个数字,其都是2的大背头幂:

 

Default = 0,

IgnoreCase = 1,

DeclaredOnly = 2,

Instance = 4,

Static = 8,

Public = 16,

NonPublic = 32,

……

 

这种做法有三个特征,正是一旦你钦赐恣意三个非负的数字,它都得以唯意气风发的意味成下边各类成员的和,而且唯有意气风发种象征方法。比方3足以用作IgnoreCase加上DeclaredOnly,12足以用作Instance加上Static。所以只要您传入Static Instance(获得静态可能实例成员卡塔 尔(英语:State of Qatar),实际上你传入的是数字12,编译器将您的数字拆成基本成员的和。

有关怎么只好动用2的整数幂,那是因为2进制中,全体的数字都由0可能1结合。若是大家将上边的列表转变为2进制:

 

Default =         00000000,

IgnoreCase =    00000001,

DeclaredOnly = 00000010,

Instance =        00000100,

Static =           00001000,

Public =           00010000,

NonPublic =      00100000,

……

 

此地做了陆个人,实际上位数的长度由最后四个分子鲜明。那么对于自由三个非负整数,它的每壹个人依然是1要么是0。大家将1看作开,0看作关,则每当中央成员都也正是开采了二个特定的位,输入中的每个人要是是1,它就等效于对应的成员处于张开状态。举例取上边的输入00011001,它的第4,5和8位是开采的,也正是说,它也正是Public

  • Static IgnoreCase。那样我们就能够将它表示为主导成员的相加了。不问可以知道,这种相加独有大器晚成种办法,荒诞不经第三种艺术了。

若想行使Flags天性,你须要和睦将值付与各类成员。值必需是2的整数幂,不然Flags天性将失去意义。

假如只想获取方式依然性质,也能够设想不行使GetMembers BindingFlags枚举的秘诀,直接行使GetMethods或GetProperties方法。以下列出了有的拿走某种特定类型成员的措施:

ConstructorInfo[]  GetConstructors()

获取指定类型包含的所有构造函数

EventInfo[]   GetEvents();

获取指定类型包含的所有事件

FieldInfo[]   GetFields();

获取指定类型包含的所有字段

MemberInfo[]   GetMembers();

获取指定类型包含的所有成员

MethodInfo[]   GetMethods();

获取指定类型包含的所有方法

PropertyInfo[]   GetProperties();

获取指定类型包含的所有属性

 

获取成员之后,我们能够经过相对应的Info类中的成员,来得到成员的值,类型,以至其它音信。必要注意的是,就算成员是私有或受保证的,通过反射相仿能够收获其值,以至能够对其值实行改造。那是ORM的贯彻根基。这里的示范大家就省去末尾时代绑定,直接将演示类型写在同三个文本中,举例:

 class Program
    {
        public static void Main(string[] args)
        {
            ReflectionDemoClass r = new ReflectionDemoClass();
            //不能在外界访问私有字段
            //r.APrivateField = "1";

            var t = typeof(ReflectionDemoClass);
            FieldInfo[] finfos =
                t.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            //通过反射获得私有成员的值 
            foreach (FieldInfo finfo in finfos)
            {
                //甚至修改私有成员的值
                if (finfo.Name == "APrivateField")
                {
                    finfo.SetValue(r, "12345");
                }
                Console.WriteLine("字段名称:{0}, 字段类型:{1}, 值为:{2}", finfo.Name, finfo.FieldType, finfo.GetValue(r));
            }
            Console.ReadKey();
        }
    }

    public class ReflectionDemoClass
    {
        private string APrivateField;

        private string AProperty { get; set; }

        public string AnotherProperty { get; set; }

        public void AMethod()
        {
            Console.WriteLine("I am a method.");
        }

        public void AnotherMethod(string s)
        {
            Console.WriteLine("I am another method, input is "   s);
        }

        public ReflectionDemoClass()
        {
            APrivateField = "a";
            AProperty = "1";
            AnotherProperty = "2";
        }
    }

项目成员除了字段,还会有属性,方法,构造函数等。能够由此Invoke调用方法。

//调用方法
            var method = t.GetMethod("AMethod");
            //方法没有输入变量
            method.Invoke(r, null);

            //方法有输入变量
            method = t.GetMethod("AnotherMethod");
            object[] parameters = { "Hello world!" };
            method.Invoke(r, parameters);

 

消灭净尽方案1:System.Reflection.Emit

简单易行来讲,正是您一丝一毫可以创设四个动态程序集,有温馨的类,方法,属性,以至以间接写IL的章程来做。

精通C#第6版第18章对Emit有详尽的演说。Emit命名空间提供了后生可畏种体制,允许在运作时协会出新的类型或程序集。这足以当作是反射的生机勃勃种类型,但又高于反射(反射只是操作,而Emit能够成立卡塔 尔(阿拉伯语:قطر‎。

四个左近的Emit的选择场景是Moq,它应用Emit在运维时,动态的创办叁个新的门类,达成全体的办法,但都是空方法,进而到达创设叁个假的品种的目标。

选用Emit构建新的品类(以致它的质量和议程卡塔 尔(英语:State of Qatar)要求对IL有必然认知。因为Emit的一大半艺术是直接被撤换为IL的。创设新的项目平常须要以下步骤:

  1. 确立三个类,并促成都部队分档期的顺序和艺术
  2. 在主函数所在的类型中,定义三个静态方法,并传到叁个施用程序域
  3. 在行使程序域中开创八个新的前后相继集
  4. 在程序聚集创造多少个新的模块
  5. 在模块中创建大家建构的类
  6. 接收ILGenerator创制项目标持有办法(蕴含构造函数卡塔尔和品质,平时,手写是不太现实的,大家需求运用ildasm.exe获得IL代码,然后再利用ILGenerator造出这一个IL代码

比方,固然大家要布局上边方法的IL代码(使用Emit卡塔尔国:

        public void AMethod()
        {
            Console.WriteLine("I am a method.");
        }

下边是亲自过问:

 public static MethodInfo EmitDemo()
        {
            //创建程序集
            AssemblyName name = new AssemblyName { Name = "MyFirstAssembly" };

            //获取当前应用程序域的一个引用
            AppDomain appDomain = System.Threading.Thread.GetDomain();

            //定义一个AssemblyBuilder变量
            //从零开始构造一个新的程序集
            AssemblyBuilder abuilder = appDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);

            //定义一个模块(Module)
            ModuleBuilder mbuilder = abuilder.DefineDynamicModule("MyFirstModule");

            //创建一个类(Class)
            TypeBuilder emitDemoClass = mbuilder.DefineType("EmitDemoClass", TypeAttributes.Public | TypeAttributes.Class);

            Type ret = typeof(void);

            //创建方法
            MethodBuilder methodBuilder = emitDemoClass.DefineMethod("AMethod", MethodAttributes.Public | MethodAttributes.Static, ret, null);

            //为方法添加代码
            //假设代码就是ReflectionDemoClass中AMethod方法的代码
            ILGenerator il = methodBuilder.GetILGenerator();
            il.EmitWriteLine("I am a method.");
            il.Emit(OpCodes.Ret);

            //在反射中应用
            Type emitSumClassType = emitDemoClass.CreateType();
            return emitSumClassType.GetMethod("AMethod");
        }

从地点的事例能够看看,大家必要和IL打交道,技术在il.Emit中写出科学的代码。大家得以因此ildasm查看IL代码,但万大器晚成IL相当长,则代码很难写对,况兼非常特别麻烦领悟。有意思味的校友能够参考:

以及 

一文中有使用Emit对setter的达成。从结果来看,其速度比不上委托快。对于必要大批量选取反射的场合,举例ORM须求经过反射为属性一个一个赋值,那么它日常也会利用相像的体制来提升品质。

 

反射:增加阅读

强盛阅读中,详细的介绍了信托 表明式树法对反射的优化。能够使用非常的数据结构进行缓存,进而进一层提升质量。对于利用何种数据结构,扩张阅读中有详实的演讲和代码。这个故事情节远远超过了貌似公司(尽管是BAT卡塔 尔(英语:State of Qatar)的面试水平,假使不是有开拓需求,无需对那上头展开浓厚钻研。

 

 

格局反射调用有多慢

主意的调用可以分成二种艺术:间接调用,委托调用和反光调用。

下边包车型客车例子表达了点子的反光调用。就算大家要通过反射改过有些属性的值,那亟需呼叫属性的setter。

public static void Main(string[] args)
        {
            var r = new ReflectionDemoClass();
            var t = typeof(ReflectionDemoClass);

            //获得属性的setter
            var pinfo = t.GetProperty("AnotherProperty");
            var setMethod = pinfo.GetSetMethod();

            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < 1000000; i  )
            {
                setMethod.Invoke(r, new object[] { "12345" });
            }

            sw.Stop();
            Console.WriteLine(sw.Elapsed   " (Reflection invoke)");

            sw.Restart();

            //直接调用setter
            for (int i = 0; i < 1000000; i  )
            {
                r.AnotherProperty = "12345";
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed   " (Directly invoke)");
        }

00:00:00.2589952 (Reflection invoke)

00:00:00.0040643 (Directly invoke)

合计调用了第一百货公司万次,从结果来看,反射消耗费时间间是一向调用的60多倍。

Dapper.net的进度超级快,近年来看源码,原本她orm的贯彻是透过编写制定大批量IL代码完成的。
利用DynamicMethod,自己编织二个给实体赋值的艺术。这种写法效用异常高,临近直接对质量赋值。比选用反射赋值作用高10倍左右。
下边分别选拔Emit,反射,直接赋值100000次来实行相比较测验。

反射 - 定义,实例与优化

在面试中,平时会调查反射的概念(操作元数据卡塔尔,能够用反射做如何(拿到程序集及其种种构件卡塔 尔(阿拉伯语:قطر‎,反射有怎么着使用情况(ORM,类别化,反类别化,值类型比较等卡塔 尔(英语:State of Qatar)。假若答得好,还会问一下什么优化反射(Emit法,委托法卡塔尔。

反射的品质远小于直接调用,但对于必定要接收的景况,它的习性而未为不可担当。对于“反射明确是招致质量差的注重缘由”这种说法,要形只影单客观的剖析。

.NET平台能够动用元数据全部的描述类型(类,结构,委托,枚举,接口卡塔尔国。多数.NET技巧,比如WCF或种类化都亟需在运转时意识项目格式。在.NET中,查看和操作元数据的动作称为反射(也可以称作元编制程序卡塔 尔(英语:State of Qatar)。

 

分分快三计划 2

 

反射就是和次序集打交道。上海教室呈现了程序集的阶层关系。通过反射大家得以:

  1. 赢得二个程序集:那叫做动态加载程序集,大概最后时期绑定。绝对的,前期绑定正是援用程序集,进而在运维时事先就加载它。得到程序集之后,就足以进一层获取个中的项目,然后再进一层拿到类型中的方法,属性的值等等。
  2. 获得程序集的托管模块。叁个主次集能够包涵三个托管模块。日常大家对程序集和档期的顺序的名字很熟识,对模块则一无所知,所以那通常没什么用,因为我们获得模块的末段指标仍然为了模块中的类型。
  3. 获得程序聚集(托管模块中的卡塔 尔(英语:State of Qatar)的门类。那个时候System.Type类起着老大首要的功能。它能够回到类型对象,之后,大家就足以得到类型的分子和方法表。得到类型对象之后,大家就足以更进一层获得类型的积极分子。
  4. 赢得类型的分子。家常便饭的情境有遍历全部属性并打字与印刷其值,反射调用方法等。ORM通过反射获得类型及其成员,然后为其赋值。

行使反射时,三个第意气风发的类型是System.Type类,其会回去加载堆上的类型对象(包含静态成员和方法表卡塔尔国。当我们要反射二个类的措施时,首先要取得它的品类对象,然后再接收GetMethods方法赢得某些方法。拿到方式之后,能够使用Invoke实行措施。

反射带给了老大苍劲的元编制程序技术,举例动态变化代码。如Ruby的元编制程序技术,它的ORM能够从数据库的Schema中央政府机构接“掘出”字段,而类本人大致不需求定义任何内容,那正是元编制程序的威力表现之后生可畏。

 

养虎遗患方案2:委托

若果急需自身写三个ORM框架,则为属性赋值和收获属性的值料定是不可制止的操作。我们得以经过Delegate.CreateDelegate建设构造四个寄托,其目的函数是性质的setter,故它有三个输入变量,未有再次回到值。当Invoke委托时,就调用了setter。编写代码时,目的在于构造三个和指标措施具名相通的信托。

代码如下:

 public static void Main(string[] args)
        {
            var r = new ReflectionDemoClass();
            var t = typeof(ReflectionDemoClass);

            //获得属性的setter
            var pinfo = t.GetProperty("AnotherProperty");
            var setMethod = pinfo.GetSetMethod();

            Stopwatch sw = new Stopwatch();
            sw.Start();

            for (int i = 0; i < 1000000; i  )
            {
                setMethod.Invoke(r, new object[] { "12345" });
            }

            sw.Stop();
            Console.WriteLine(sw.Elapsed   " (Reflection invoke)");

            sw.Restart();

            //直接调用setter
            for (int i = 0; i < 1000000; i  )
            {
                r.AnotherProperty = "12345";
            }
            sw.Stop();
            Console.WriteLine(sw.Elapsed   " (Directly invoke)");

            //委托调用
            //建立一个DelegateSetter类型的委托
            //委托的目标函数是ReflectionDemoClass类型中AnotherProperty属性的setter
            DelegateSetter ds = (DelegateSetter) Delegate.CreateDelegate(typeof(DelegateSetter), r,
                    //获得属性的setter
                    typeof(ReflectionDemoClass).GetProperty("AnotherProperty").GetSetMethod());

            sw.Reset();
            sw.Start();
            for (int i = 0; i < 1000000; i  )
            {
                ds("12345");
            }

            sw.Stop();

            Console.WriteLine(sw.Elapsed   " (Delegate invoke)");

            Console.ReadKey();
        }

结果:

00:00:00.3690372 (Reflection invoke)

00:00:00.0068159 (Directly invoke)

00:00:00.0096351 (Delegate invoke)

能够看看委托调用远远凌驾反射调用,纵然它依旧未有直接调用急迅。对于三个通用的应用方案,我们必要定义七个最最相符项指标委托

  • Func<object, object[], object>(选拔一个object类型与object[]品种的参数,以致重临叁个object类型的结果卡塔尔。

因为任何事物都以表明式,所以本来也得以通过表达式来实行多少个信托。固然应用表明式比较复杂,但大家得以令表明式选用相似项指标信托,防止每回委托调用都要表明不一致的寄托。

该小说使用委托 表明式树法,给出了四个相像的解决方案。它的结果申明,委托的进度略慢于直接调用,但远快过反射。

public static void ReflectSetter(object obj, string propertyName, object propertyValue)
{
var type = obj.GetType();
var propertyInfo = type.GetProperty(propertyName);
propertyInfo.SetValue(obj, propertyValue,null);
}

方式反射调用为啥慢

反射速度慢有如下多少个原因:

  • 反射首先要操作和寻觅元数据,而直接调用查找元数据这一步是在编写翻译(jit卡塔 尔(阿拉伯语:قطر‎时
  • 反射调用方法时,未有经过编译器jit的优化。而直白调用的代码是经jit优化后的本地代码
  • 反射调用方法须求检讨输入参数的品类,那是在运作时技艺打铁趁热的,而直接调用的代码检查项目是在编译时
  • 就算能够通过前边所讲的三种办法优化反射,反射的质量依旧远远不比间接调用

资料:

利用反射调用方法比直接调用慢上数十倍。反射优化的常常有措施只有一条路:避开反射。但是,避开的点子可分为三种:

  1. 用委托和表明式树去调用。(绕弯子卡塔 尔(英语:State of Qatar)

2. 生成间接调用代码,代替反射调用。能够运用System.Reflection.Emit,但万后生可畏措施过于复杂,必要极度熟习IL才足以写出不错的代码。

这两种方法的快慢齐趋并驾,扩展阅读中,有应用委托调用加强反射质量的事例。大家透过表明式树来创建强类型的寄托,到达调用方法的目标(调用方法也是三个表明式卡塔尔国。那能够大大减少耗费时间,进步品质。

public static Action<T, object> EmitSetter<T>(string propertyName)
{
var type = typeof(T);
        var dynamicMethod = new DynamicMethod("EmitCallable", null, new[] { type, typeof(object) }, type.Module);
        var iLGenerator = dynamicMethod.GetILGenerator();


        var callMethod = type.GetMethod("set_"   propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
        var parameterInfo = callMethod.GetParameters()[0];
        var local = iLGenerator.DeclareLocal(parameterInfo.ParameterType, true);


        iLGenerator.Emit(OpCodes.Ldarg_1);
        if (parameterInfo.ParameterType.IsValueType)
        {
            // 如果是值类型,拆箱
            iLGenerator.Emit(OpCodes.Unbox_Any, parameterInfo.ParameterType);
        }
        else
        {
            // 如果是引用类型,转换
            iLGenerator.Emit(OpCodes.Castclass, parameterInfo.ParameterType);
        }


        iLGenerator.Emit(OpCodes.Stloc, local);
        iLGenerator.Emit(OpCodes.Ldarg_0);
        iLGenerator.Emit(OpCodes.Ldloc, local);


        iLGenerator.EmitCall(OpCodes.Callvirt, callMethod, null);
        iLGenerator.Emit(OpCodes.Ret);


        return dynamicMethod.CreateDelegate(typeof(Action<T, object>)) as Action<T, object>;
    }

分分快三计划 3分分快三计划 4

image.png

我们新建贰个简约实体,增加二个属性。

private void Button_Click(object sender, RoutedEventArgs e)
{
Model model = new Model();
        TimeSpan ts1;
        DateTime time1 = DateTime.Now;          

        var emitSetter=EmitSetter<Model>("Name");

        for (int i = 0; i < 100000; i  )
        {
            emitSetter(model, "测试");
        }
        DateTime time2 = DateTime.Now;

        ts1 = time2 - time1;
        Console.WriteLine("emit:" ts1.TotalMilliseconds);

        DateTime t3 = DateTime.Now;
        for (int i = 0; i < 100000; i  )
        {
            ReflectSetter(model,"Name", "测试");
        }
        DateTime t4 = DateTime.Now;
        ts1 = t4 - t3;
        Console.WriteLine("reflect" ts1.TotalMilliseconds);

        DateTime t5 = DateTime.Now;
        for (int i = 0; i < 100000; i  )
        {
            model.Name = "测试";
        }
        DateTime t6 = DateTime.Now;
        ts1 = t6 - t5;
        Console.WriteLine("直接赋值" ts1.TotalMilliseconds);
    }
public class Model
{
public string Name { get; set; }
}

View Code

应用Emit实施时间概况是直接赋值的两倍,使用反射实施时间大概是一贯赋值的七十多倍。Emit作用是反光的十倍以上。

 

上边是反光的写法

上边进行测验

本文由分分快三计划发布,转载请注明来源

关键词: 分分快三计划 C# .NET技术