Emit动态生成代码

摘要:
TypeAttributes.Public);newType[]{typeof(string)}));typeof(控制台).GetMethod(“ReadLine”));使用系统;Console.ReadLine();使用系统的完整代码;使用System.Reflection;使用System.Reflection.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();
  }
}

运行结果,
Emit动态生成代码第1张

完整代码

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生成构造函数和属性

 

免责声明:文章转载自《Emit动态生成代码》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇BLDC开发笔记5.过流保护时瞬时电流采样时刻点linux中编译安装时的make test下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

最全Pycharm教程(10)——Pycharm调试器总篇

  最全Pycharm教程(1)——定制外观   最全Pycharm教程(2)——代码风格   最全Pycharm教程(3)——代码的调试、执行   最全Pycharm教程(4)——有关Python解释器的相关配置   最全Pycharm教程(5)——Python快捷键相关设置   最全Pycharm教程(6)——将Pycharm作为Vim编...

web 大文件分片上传处理

这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数 下面直接贴代码吧,一些难懂的我大部分都加上注释了: 上传文件实体类: 看得出来,实体类中已经有很多我们需要的功能了,还有实用的属性。如MD5秒传的信息。 首先是文件数据接收逻辑,负责接收控件上传的文件块数据,然后写到服务器的文件中...

VSTO:使用工作簿

一、新建工作簿 以编程方式创建工作簿时,所创建的将是一个本机Microsoft.Office.Interop.Excel.Workbook对象,而不是Microsoft.Office.Tools.Excel.Workbook宿主项。 1.单击工作表中的按钮新建工作簿 在工作簿Sheet1中新建一个按钮,在按钮的单击事件中编写以下代码新建一个工作簿: usi...

《放弃繁琐的if-else》开启Assert断言的新时代

一、场景再现   我们平时在service操作数据库,难免会出现这种情况:   if(null == result){   }else{   }   这样的代码会吞噬掉你有限的代码空间,虽然通俗易懂,但一旦爆炸式的袭来,将会是一场阅读灾难。 终于,在java8到来之际,带来了福音,利用option解决了NullPoint问题,不用在代码里面判空拦截(不懂的...

1个开发如何撑起一个过亿用户的小程序

本文由云+社区发表 2018年12月,腾讯相册累计用户量突破1亿,月活1200万,阿拉丁指数排行 Top 30,已经成为小程序生态的重量级玩家。 三个多月来,腾讯相册围绕【在微信分享相册照片】这一核心场景,快速优化和新增一系列社交化功能,配合适当的运营,实现累计用户量突破1亿,大大超过预期。 可是,谁曾想到,这样一个亿级体量的小程序,竟然是一个开发做出来的...

各种数据库的批量插入操作_Oracle

最近工作中需要优化以前各种的Excel批量导入功能,目前将能优化的方面做个记录。 选用技术:   目前.Net可以访问Oracle常用的Dll,有三种: 微软自带的 System.Data.OracleClient Oracle 公司提供的 Oracle.DataAccess System.Data.OleDb  通过比对以后,使用第二种,其原因如下:...