zoukankan      html  css  js  c++  java
  • C#中反射的使用(How to use reflect in CSharp)(3)Emit的使用

    Emit意在动态构建一个可以执行(当然也就可以反射)或者只可以反射的动态库。

    个人认为在不得不使用反射的情况下,使用Emit会使得效率提升空间很大。亦或者动态插件模式的软件设计中会用到。

    依然2%的废话和98%的代码:

     1 using System;
     2 using System.Reflection;
     3 using System.Reflection.Emit;
     4 
     5 namespace ReflectionTest
     6 {
     7     class Program
     8     {
     9         static void Main(string[] args)
    10         {
    11             //Emit
    12             /*
    13              Emit的知识隶属于反射的一部分,也是比较偏门的一部分。
    14              在出现Dynamic和匿名类之后,它会有更小的用武之地,但仍然属于Reflection的知识范畴。
    15              区别于“正常”的反射,Emit是动态的构建一个类,
    16              比如,现在你没有Person.Dll,没有项目可以引用,没有可以反射的对象
    17              那么你可能会想到Emit,它可以使你用代码构建出一个Person类,你甚至可以把动态构建的类保存成DLL,然后使用反射调用
    18              虽然也是用C#去实现,但语法风格大不相同,强硬的理解,可以理解Emit暴漏给C#一些接口,让你去操作IL,然后生成动态库
    19              在这次的blog中,我们的目的就是用代码构建出这个person类。OK,Let's start
    20              */
    21             //STEP 1. Give him a name
    22             var assemblyName = new AssemblyName("PersonMoudle");
    23 
    24             //STEP 2. Build a assembly
    25             var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
    26                 AssemblyBuilderAccess.RunAndSave);
    27 
    28             //STEP 3. Add a moudle
    29             var moudle = assemblyBuilder.DefineDynamicModule("PersonMoudle", "PersonMoudle.dll");
    30 
    31             //SETP 4. Add a Class
    32             var typePart = moudle.DefineType("Person", TypeAttributes.Public);
    33 
    34             //SETP 5. Add a method for this Class
    35             var methodPart = typePart.DefineMethod("SayHi", MethodAttributes.Public, null, null);
    36 
    37             //STEP 6. Imp the method
    38             var il = methodPart.GetILGenerator();
    39             il.EmitWriteLine("Hi! I'm SayHi method!");
    40             il.Emit(OpCodes.Ret);
    41 
    42             typePart.CreateType();
    43             assemblyBuilder.Save("PersonMoudle.dll");
    44 
    45             //再比如,构建一个exe
    46             var ad = AppDomain.CurrentDomain;
    47             var am = new AssemblyName {Name = "TestEmit"};
    48             var ab = ad.DefineDynamicAssembly(am, AssemblyBuilderAccess.Save);
    49             var mb = ab.DefineDynamicModule("testmod", "输出一句话.exe");
    50             var tb = mb.DefineType("TestEmit.Test", TypeAttributes.Public);
    51             var metb = tb.DefineMethod("ConsoleWord", MethodAttributes.Public | MethodAttributes.Static, typeof (void),
    52                 null);
    53             ab.SetEntryPoint(metb);
    54             ILGenerator il1 = metb.GetILGenerator();
    55             il1.EmitWriteLine("Hello World");
    56             il1.EmitWriteLine("按任意键退出……");
    57             il1.Emit(OpCodes.Call, typeof (Console).GetMethod("ReadKey",new Type[]{}));//指定无参数的重载。生产环境的代码中应该有更加严格判断,具体指定个某个方法请翻前篇的文章。
    58             il1.Emit(OpCodes.Ret);
    59             tb.CreateType();
    60             ab.Save("输出一句话.exe");
    61             Console.ReadKey();
    62         }
    63     }
    64 }

    我们可以看到,执行完这个之后,在Debug里会生成我们想要的PersonMoudle.dll和输出一句话.exe、反编译后的dll和exe的执行效果:

  • 相关阅读:
    mysql-5-aggregation
    mysql-4-functions
    mysql-3-orderby
    技术之心 | 云信和TA们携手打响防疫战
    疫情下的传统商企自救|4个Tips搭建销量过亿直播间
    那些2019年会爆发的泛娱乐黑科技风口
    流量难、获客难、增长难?增长黑客思维“解救”B端业务
    【翻译】Facebook全面推出Watch Party,可多人线上同看直播视频
    深入浅出聊一聊Docker
    C++写日志方法调试
  • 原文地址:https://www.cnblogs.com/xidu/p/4269578.html
Copyright © 2011-2022 走看看