详解c# Emit技术

2023-11-06

我们常常有一个应用场景,由我们的C#代码,动态生成一个EXE,其应用场景可以非常多,比如软件授权,可以输入授权信息后,生成一个授权的DLL等,那如何实现这个功能呢,就要提到一个技术Emit。

1、Emit概述
Emit,可以称为发出或者产生。在Framework中,与Emit相关的类基本都存在于System.Reflection.Emit命名
空间下。可见Emit是作为反射的一个元素存在的。说道反射,大家应该都不陌生,它允许我们查看程序集的元素据,从而取得形如程序集包含哪些类型,类型包
含哪些方法等等大量的信息。但是反射也仅能够‘看’,而Emit则可以在运行时动态生成代码。接下来就来看看如何用Emit生成代码。

2、程序集(Assembly)和模块(Managed Module)
程序集是一个或多个模块、资源文件的逻辑性分组,其次程序集是重用,安全性和版本控制的最小单元。我们所见到的DLL、EXE都可以称为一个Assembly,一个Assembly里面包含多个Module,不过通常,我们VS编译的时候,会只编译一个Module,假如在一个Assembly中要编译多个Module,则要借助csc.exe实现。

3、动态生成代码操作
定义程序集

//定义一个程序集的名称
 var asmName = new AssemblyName("MyClass");
 
//首先就需要定义一个程序集
 var defAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);

定义模块,和指定程序集的保存名称

//定义一个构建类
var defModuleBuilder = defAssembly.DefineDynamicModule("MyModule", "MyAssembly.dll");

定义一个类 和方法

//定义一个类
 var defClassBuilder =defModuleBuilder.DefineType("MyClass", TypeAttributes.Public);
 //定义一个方法
var methodBldr = defClassBuilder.DefineMethod("MyMethod",
  MethodAttributes.Public,
   null,//返回类型
   null//参数的类型
 );

以上通过创建,已经确定了程序集和模块,也定义了当前模块中的一个类和方法,但这个类的MyMethod方法只定义了一个声明,并没有定义实体操作,以下就需要应用到Emit技术中一个技术OpCode。

OpCode 是描述中间语言 (IL) 指令。这个指令非常多,可以查看微软官网:https://docs.microsoft.com/zh-cn/dotnet/api/system.reflection.emit.opcodes?view=netframework-4.8

通过OpCode我们可以定义方法的内容如下:

//获取IL生成器
      var il = defMethodBuilder.GetILGenerator();
      //定义一个字符串
      il.Emit(OpCodes.Ldstr, "生成的第一个程序");
      //调用一个函数
      il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
      //返回到方法开始(返回)
      il.Emit(OpCodes.Ret);
//获取IL生成器
      var il = defMethodBuilder.GetILGenerator();
      //定义一个字符串
      il.Emit(OpCodes.Ldstr, "生成的第一个程序");
      //调用一个函数
      il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
      //返回到方法开始(返回)
      il.Emit(OpCodes.Ret);

通过以上的定义,我们完成了一个程序集、模块、类和方法的定义,我们怎么把以上的定义的信息进行创建和c#教程保存,需要调用以下函数:

//创建类型
  defClassBuilder.CreateType();
 
  //保存程序集
  defAssembly.Save("MyAssemblydll");

我们可以在运行程序看到如下效果:

在这里插入图片描述

以下通过创建程序集,并且调用的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
 
namespace ConsoleApp1
{
  class Program
  {
    static void Main(string[] args)
    {
 
      CreateAssembly();
      LoadAssembly();
 
      Console.ReadKey();
    }
 
    public static void LoadAssembly()
    {
      var ass = AppDomain.CurrentDomain.Load("MyAssembly");
      var m = ass.GetModule("MyModule");
      var ts = m.GetTypes();
      var t = ts.FirstOrDefault();
      if (t != null)
      {
        object obj = Activator.CreateInstance(t);
        var me = t.GetMethod("MyMethod");
        me.Invoke(obj, null);
      }
    }
    public static void CreateAssembly()
    {
 
 
      //定义一个程序集的名称
      var asmName = new AssemblyName("MyAssembly");
 
      //首先就需要定义一个程序集
      var defAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.RunAndSave);
      //定义一个构建类
      var defModuleBuilder = defAssembly.DefineDynamicModule("MyModule", "MyAssembly.dll");
 
 
      //定义一个类
      var defClassBuilder = defModuleBuilder.DefineType("MyClass", TypeAttributes.Public);
 
      //定义一个方法
      var defMethodBuilder = defClassBuilder.DefineMethod("MyMethod",
        MethodAttributes.Public,
        null,//返回类型
        null//参数类型
        );
      //获取IL生成器
      var il = defMethodBuilder.GetILGenerator();
      //定义一个字符串
      il.Emit(OpCodes.Ldstr, "生成的第一个程序");
      //调用一个函数
      il.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
      //返回到方法开始(返回)
      il.Emit(OpCodes.Ret);
 
      //创建类型
      defClassBuilder.CreateType();
 
      //保存程序集
      defAssembly.Save("MyAssembly.dll");
    }
 
  }
}

显示效果如下:

在这里插入图片描述

以上就是详解c# Emit技术的详细内容

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详解c# Emit技术 的相关文章

  • 一、红外遥控介绍(NEC协议)

    目录 1 1 红外线的介绍 1 2 红外遥控器的工作原理 1 3 NEC协议的介绍 1 引导码的组成 2 地址码 3 数据码 4 反码 5 连发码 1 4 红外接受装置 1 在数码管显示红外解码遥控器的按键值 1 1 红外线的介绍 红外是红

随机推荐

  • Kitti数据集标签中yaw角在不同坐标系的转换

    KITTI数据集中坐标系的定义如下图 相机坐标系 激光雷达坐标系 在标签文件 label 中 最后一个值为物体前进方向与x轴夹角的弧度值 在相机坐标系下 且以顺时针为正 逆时针为负 举个例子 如上图第一个car数据为例 其前进方向与x轴夹角
  • 三、IOC容器原理

    三 IOC容器原理 1 概述 Sun ONE技术体系下的IOC容器有 轻量级的有Spring Guice Pico Container Avalon HiveMind 重量级的有EJB 不轻不重的有JBoss Jdon等等 Spring框架
  • nodejs安装

    CentOS7安装NodeJS 1 官网下载二进制文件 https nodejs org en download 2 下载后上传到目标位置 3 解压包 依次执行 cd soft nodejs xz d node v12 18 2 linux
  • Python3 + xpath + excel 实现对boss直聘网的爬取

    一 项目简介 1 内容 抓取boss直聘网上广州地区的 python 相关工作的招聘信息 并且将招聘信息循环保存在excel表中 2 目标网站 https www zhipin com c101280100 query python pag
  • Linux中用gdb 查看代码堆栈的信息

    core dump 一般是在segmentation fault 段错误 的情况下产生的文件 需要通过ulimit来设置才会得到的 调试的话输入 gdb filename core filename就是产生core文件的可执行文件 core
  • Windows server 远程桌面连接用户不活动自动注销配置

    Windows server 远程桌面连接用户不活动自动注销配置
  • VMware三种网络模式配置详解。

    VMware网络 本质上不会配置VMware网络 是因为对其不够熟悉 VMware提供了三种可靠的网络模式 我相信只要了解了他们的区别 配置起来应该是如鱼得水的 如果还在为你的虚拟机上不了网而发愁 那么请跟随我的脚步 让我们来探究他们到底有
  • Flowable 用户问题

    Flowable用户和系统用户问题 springboot集成flowable modeler 实现免登 权限管理 Flowable引擎使用统一权限管理
  • 《信号与系统》解读 第4章 连续信号的离散化:采样与采样定理、奈奎斯特准则、脉冲编码调制PCM

    前言 如果你对采样定理和奈奎斯特准则一知半解 本文将给茅塞顿开 如果你对为什么采样频率必须大于等于原始信号的带宽的2倍 本文将给你答案 目录 1 信号与系统的模型 2 为什么要对连续信号离散化 3 连续信号离散化 采样 的模型 3 1 采样
  • 使用Hexo搭建博客并部署到Github

    一 博客环境搭建 Hexo 是一个静态博客框架 基于 Node js 将 Markdown 文章通过渲染引擎 生成一个静态网页 再结合 Git 命令 ssh Hexo 是一个快速 简洁且高效的博客框架 Hexo 使用 Markdown 或其
  • 深入理解 Java 垃圾回收机制

    一 垃圾回收机制的意义 java 语言中一个显著的特点就是引入了java回收机制 是c 程序员最头疼的内存管理的问题迎刃而解 它使得java程序员在编写程序的时候不在考虑内存管理 由于有个垃圾回收机制 java中的额对象不在有 作用域 的概
  • 解决Excel打开UTF-8编码的CSV文件乱码的问题

    解决Excel打开UTF 8编码的CSV文件乱码的问题 引用自 https en wikipedia org wiki Comma separated values CSV formats are not limited to a part
  • 透彻解析Qt入门级项目——贪吃蛇游戏

    1 项目目的 本项目主要通过编写贪吃蛇游戏来学习 熟悉Qt中封装的类 2 编译环境 VS2019 Qt5 9 3 功能实现 主要实现下面所列基本功能 控制贪吃蛇吃食物 表示蛇 控制贪吃蛇上下左右移动 控制食物的随机分配 控制蛇的增长 暂停游
  • MATLAB上关于复数矩阵的转置与共轭知识详解

    首选随机用A randn 2 2 randn 2 2 1i生成一个二维的复数矩阵 执行后结果如下 A 3 5784 0 7254i 1 3499 0 7147i 2 7694 0 0631i 3 0349 0 2050i 执行 A 得到如下
  • DRM(Direct Rendering Manager)学习简介

    DRM DRM是Linux目前主流的图形显示框架 相比FB架构 DRM更能适应当前日益更新的显示硬件 比如FB原生不支持多层合成 不支持VSYNC 不支持DMA BUF 不支持异步更新 不支持fence机制等等 而这些功能DRM原生都支持
  • 堆栈内存地址

    catalog 有两个信息 B gt A 即栈空间地址 gt 堆空间地址 比如 你的临时变量的地址 是 0x666666 全局变量的地址0x222222 总之 栈空间地址 gt 堆空间地址 栈空间 依据申请变量的次序 地址是 从B地址开始递
  • Ubuntu 20.04及pytorch安装

    转载自 https blog csdn net xjgao75 article details 105869699 侵权可删 只作为笔记 Ubuntu 20 04安装及pytorch深度学习框架配置 Ubuntu 20 04安装 启动U盘制
  • Unity-NGUI物体扫光特效

    先看效果 最近搞了多张卡牌合成新卡牌后 新卡牌在放回背包后闪亮一下 没搞过Shader 但前人已经造好轮子 研究后 记录下 方便以后使用 效果如下 文章详情请移步 Unity NGUI物体扫光特效
  • leecode刷算法C++

    共11道数组 字符串相关题目 大多数为简单 我分为三类 分别为翻转问题 元素重复问题和其它类 使用C 翻转问题包括轮转数组 翻转字符串 整数翻转这3道题 元素重复题目包括删除有序数组中的重复项 存在重复元素 只出现一次的数字 字符串中的第一
  • 详解c# Emit技术

    我们常常有一个应用场景 由我们的C 代码 动态生成一个EXE 其应用场景可以非常多 比如软件授权 可以输入授权信息后 生成一个授权的DLL等 那如何实现这个功能呢 就要提到一个技术Emit 1 Emit概述 Emit 可以称为发出或者产生