• Emit动态生成代码


    Emit动态生成代码

    引用:秒懂C#通过Emit动态生成代码

    首先需要声明一个程序集名称,

    // specify a new assembly name
    var assemblyName = new AssemblyName("Kitty");

    从当前应用程序域获取程序集构造器,

    // create assembly builder 
    var assemblyBuilder=AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);

    有几种动态程序集构造访问限制:

    • AssemblyBuilderAccess.Run; 表示程序集可被执行,但不能被保存。  
    • AssemblyBuilderAccess.Save; 表示程序集可被保存,但不能被执行。  
    • AssemblyBuilderAccess.RunAndSave; 表示程序集可被保存并能被执行。
    • AssemblyBuilderAccess.ReflectionOnly; 表示程序集只能用于反射上下文环境中,不能被执行。 
    • AssemblyBuilderAccess.RunAndCollect; 表示程序集可以被卸载并且内存会被回收。

    在程序集中构造动态模块,

    // create module builder 
    var moduleBuilder = assemblyBuilder.DefineDynamicModule("KittyModule", "Kitty.exe");

    模块即是代码的集合,一个程序集中可以有多个模块。并且理论上讲,每个模块可以使用不同的编程语言实现,例如C#/VB。
    构造一个类型构造器,

    // create type builder for a class 
    var typeBuilder = moduleBuilder.DefineType("HelloKittyClass", TypeAttributes.Public);

    通过类型构造器定义一个方法,获取方法构造器,获得方法构造器的IL生成器,通过编写IL代码来定义方法功能。

    // create method builder
    var methodBuilder = typeBuilder.DefineMethod(
      "SayHelloMethod",
      MethodAttributes.Public | MethodAttributes.Static,
      null,
      null);
     
    // then get the method il generator
    var il = methodBuilder.GetILGenerator();
     
    // then create the method function
    il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
    il.Emit(OpCodes.Call, 
      typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
    il.Emit(OpCodes.Call, typeof(Console).GetMethod("ReadLine"));
    il.Emit(OpCodes.Pop); // we just read something here, throw it.
    il.Emit(OpCodes.Ret);

    创建类型,

    // then create the whole class type
    var helloKittyClassType = typeBuilder.CreateType();

    如果当前程序集是可运行的,则设置一个程序入口,

    // set entry point for this assembly
    assemblyBuilder.SetEntryPoint(helloKittyClassType.GetMethod("SayHelloMethod"));

    将动态生成的程序集保存成磁盘文件,

    // save assembly
    assemblyBuilder.Save("Kitty.exe");

    此时,通过反编译工具,将Kitty.exe反编译成代码,

    using System;
    
    public class HelloKittyClass
    {
      public static void SayHelloMethod()
      {
        Console.WriteLine("Hello, Kitty!");
        Console.ReadLine();
      }
    }

    运行结果,

    完整代码

    using System;
    using System.Reflection;
    using System.Reflection.Emit;
    
    namespace EmitIntroduction
    {
      class Program
      {
        static void Main(string[] args)
        {
          // specify a new assembly name
          var assemblyName = new AssemblyName("Kitty");
    
          // create assembly builder
          var assemblyBuilder = AppDomain.CurrentDomain
            .DefineDynamicAssembly(assemblyName, 
              AssemblyBuilderAccess.RunAndSave);
    
          // create module builder
          var moduleBuilder = 
            assemblyBuilder.DefineDynamicModule(
              "KittyModule", "Kitty.exe");
    
          // create type builder for a class
          var typeBuilder = 
            moduleBuilder.DefineType(
              "HelloKittyClass", TypeAttributes.Public);
    
          // create method builder
          var methodBuilder = typeBuilder.DefineMethod(
            "SayHelloMethod",
            MethodAttributes.Public | MethodAttributes.Static,
            null,
            null);
    
          // then get the method il generator
          var il = methodBuilder.GetILGenerator();
    
          // then create the method function
          il.Emit(OpCodes.Ldstr, "Hello, Kitty!");
          il.Emit(OpCodes.Call, 
            typeof(Console).GetMethod(
            "WriteLine", new Type[] { typeof(string) }));
          il.Emit(OpCodes.Call, 
            typeof(Console).GetMethod("ReadLine"));
          il.Emit(OpCodes.Pop); // we just read something here, throw it.
          il.Emit(OpCodes.Ret);
    
          // then create the whole class type
          var helloKittyClassType = typeBuilder.CreateType();
    
          // set entry point for this assembly
          assemblyBuilder.SetEntryPoint(
            helloKittyClassType.GetMethod("SayHelloMethod"));
    
          // save assembly
          assemblyBuilder.Save("Kitty.exe");
    
          Console.WriteLine(
            "Hi, Dennis, a Kitty assembly has been generated for you.");
          Console.ReadLine();
        }
      }
    }

    下载完整代码

    进一步阅读使用Emit生成构造函数和属性

     

  • 相关阅读:
    zbb20170604 在linux (64bit)下安装rar for linux
    zbb20170601 oracle 存储过程 函数 包
    zbb20170601 oracle PL/SQL 语句块 游标 自定义游标 异常处理EXCEPTION
    5、Spring+Struts2+MyBatis+分页(mybatis无代理)增删改查
    2、枚举
    3、时间和随机数
    4、Spring+MyBatis增删改查
    3、Spring的AOP详解和案例
    2、Spring的 IoC详解(第一个Spring程序)
    1、Spring概述
  • 原文地址:https://www.cnblogs.com/bruceleeliya/p/4122473.html
Copyright © 2020-2023  润新知