Emit(动态方法生成)技术是一种在运行时动态生成和执行代码的技术。它的产生背景可以追溯到早期的.NET Framework版本。

在早期的.NET Framework中,开发人员通常使用反射来动态创建和执行代码。反射允许开发人员在运行时获取类型信息并调用其成员,但它的性能相对较低。每次使用反射调用方法时,都需要进行类型解析、成员查找和参数匹配等操作,这会导致一定的性能开销。

为了提高性能并提供更灵活的动态代码生成功能,微软引入了Emit技术。Emit是一个基于IL(Intermediate Language)的API,它允许开发人员直接生成IL指令并创建动态方法。通过使用Emit技术,开发人员可以在运行时生成高效且灵活的代码,并且避免了反射带来的性能开销。

Emit技术主要用于以下几个方面:

1. 动态代理:通过使用Emit技术,可以在运行时生成代理类来实现接口或继承关系的代理。这对于实现AOP(面向切面编程)和其他动态代理场景非常有用。

2. 表达式树:表达式树是一种将代码表示为对象树的方式,可以在运行时动态生成和执行代码。Emit技术可以用于创建和操作表达式树,从而实现更高级的动态代码生成和查询功能。

3. 动态代码生成:Emit技术允许开发人员在运行时生成动态方法,并直接操作IL指令。这对于需要高度灵活性和性能的场景非常有

下面我们要动态生成如下类

    public class MyDynamicType
{
public int NumberField = 0; public int NumberProp { get; set; } public MyDynamicType(int numberField)
{
this.NumberField = numberField;
} public void ConsoleMethod()
{
Console.WriteLine("欢迎来到高级班学习");
} public int MyMethod(int para)
{
return 2 * para;
}
}

Emit 动态生成type

            AssemblyBuilder assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("DynamicAssemblyExample"), AssemblyBuilderAccess.RunAndCollect);

            // 对于单个模块程序集,模块名称通常为;程序集名称加上扩展名。
ModuleBuilder modulebuilder = assemblyBuilder.DefineDynamicModule("MyModal"); //托管模块
TypeBuilder typebuilder = modulebuilder.DefineType("MyDynamicType", TypeAttributes.Public);
Type type= typebuilder.CreateType();

Emit 定义字段、构造函数

            // 在Type中生成公有字段
FieldBuilder fieldBuilder = typebuilder.DefineField("NumberField", typeof(int), FieldAttributes.Public); // 定义一个接受整数参数的构造函数,储存在public区域。
Type[] parameterTypes = { typeof(int) };
ConstructorBuilder ctor1 = typebuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, parameterTypes);

Emit动态生成构造函数

            //中间语言的生成者
ILGenerator ctor1IL = ctor1.GetILGenerator(); //对于构造函数,参数0是对新
//实例。在调用base之前将其推到堆栈上
//类构造函数。指定的默认构造函数
//通过传递
//类型(Type.EmptyTypes)到GetConstructor。 ctor1IL.Emit(OpCodes.Ldarg_0);
ctor1IL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); //在推送参数之前,先将实例推送到堆栈上
//将被分配给私有字段m\u编号。
ctor1IL.Emit(OpCodes.Ldarg_0);
ctor1IL.Emit(OpCodes.Ldarg_1);
ctor1IL.Emit(OpCodes.Stfld, fieldBuilder);
ctor1IL.Emit(OpCodes.Ret);

Emit动态生成方法

            MethodBuilder consoleMethod = typebuilder.DefineMethod("ConsoleMethod", MethodAttributes.Public | MethodAttributes.Static, null, null);
ILGenerator consoleMethodIL = consoleMethod.GetILGenerator();
consoleMethodIL.Emit(OpCodes.Ldstr, "欢迎来到高级班第15期进阶学习");
consoleMethodIL.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));
consoleMethodIL.Emit(OpCodes.Ret); //写IL最后一定要Ret MethodBuilder AddMethod = typebuilder.DefineMethod("AddMethod", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new Type[] { typeof(int), typeof(int) });
ILGenerator AddMethodIL = AddMethod.GetILGenerator();
AddMethodIL.Emit(OpCodes.Ldarg_0);
AddMethodIL.Emit(OpCodes.Ldarg_1);
AddMethodIL.Emit(OpCodes.Add_Ovf_Un);
AddMethodIL.Emit(OpCodes.Ret);

C# Emit动态生成代码的更多相关文章

  1. Emit动态生成代码

    Emit动态生成代码 引用:秒懂C#通过Emit动态生成代码 首先需要声明一个程序集名称, // specify a new assembly name var assemblyName = new ...

  2. 秒懂C#通过Emit动态生成代码 C#使用Emit构造拦截器动态代理类

    秒懂C#通过Emit动态生成代码   首先需要声明一个程序集名称, 1 // specify a new assembly name 2 var assemblyName = new Assembly ...

  3. 秒懂C#通过Emit动态生成代码

    首先需要声明一个程序集名称, 1 // specify a new assembly name 2 var assemblyName = new AssemblyName("Kitty&qu ...

  4. Emit动态生成代理类用于监控对象的字段修改

    利用Emit动态生成代理对象监控对象哪些字段被修改,被修改为什么值 被Register的对象要监控的值必须是Virtual虚类型 必须使用CreateInstance创建对象 必须使用DynamicP ...

  5. CodeTypeDeclaration,CodeMemberProperty动态生成代码

    由于是CodeDom些列,所以先介绍几个CodeDom表达式: :CodeConditionStatement:判断语句即是if(condition){} else{},看最全的那个构造函数: pub ...

  6. Emit 自动生成IL代码,注入代码

    Spring 框架中的注入代码,以及自动生成对接口的实现,则根据il代码注入 Emit学习(1)-Emit概览 一.Emit概述 Emit,可以称为发出或者产生.在Framework中,与Emit相关 ...

  7. Android 动态生成布局 (多层嵌套)

    Android 除了能够载入xml文件,显示布局外,也能够代码生成布局,并通过setContentView(View view)方法显示布局.单独的一层布局,如一个主布局加一个控件(如Button\i ...

  8. C# Emit动态代理生成一个实体对象

    /// <summary> /// 使用Emit动态代理收集实体信息 /// </summary> /// <typeparam name="T"&g ...

  9. 动态生成一个设定好特殊样式的Tlabel,快速生成代码

    动态生成一个设定好特殊样式的Tlabel,快速生成代码: 1.自己先在可视化界面设定一个Label,像这样: 2.选择label,快捷键ctrl+C 复制,粘贴带代码编辑器去,会生成一段这样的窗体代码 ...

  10. 在后台代码中动态生成pivot项并设置EventTrigger和Action的绑定

    最近在做今日头条WP的过程中,遇到需要动态生成Pivot项的问题.第一个版本是把几个频道写死在xaml里了,事件绑定也写在xaml里,每个频道绑定一个ObservableCollection<A ...

随机推荐

  1. 【C++】【图像处理】均值滤波 and 高斯滤波 and 中值滤波 (低通滤波器)and Sobel算子边缘提取算法解析(以.raw格式的图像为基础进行图像处理、gray levels:256)

    1 void meanFilter(BYTE* image, int width, int height, BYTE* outImg) 2 { 3 //均值滤波 4 int smth[9]; 5 in ...

  2. Java反序列化漏洞-CC1利用链分析

    @ 目录 一.前置知识 1. 反射 2. Commons Collections是什么 3. 环境准备 二.分析利用链 1. Transformer 2. InvokeTransformer 执行命令 ...

  3. win10安装WSL

    一.什么是WSL? Windows Subsystem for Linux 简称 WSL,是一个在Windows 10上能够运行原生Linux二进制可执行文件(ELF格式)的兼容层. 二.如何安装WS ...

  4. c#中用System.Diagnostics.Process.Start(Path.GetFullPath(“vlc.exe.lnk“), url);用vlc的快捷方式打开http的url不起作用?

    vlc.exe.lnk双击这个文件,能正常打开vlc,但是用System.Diagnostics.Process.Start(Path.GetFullPath("vlc.exe.lnk&qu ...

  5. 2023-05-13:你现在手里有一份大小为 n x n 的 网格 grid, 上面的每个 单元格 都用 0 和 1 标记好了其中 0 代表海洋,1 代表陆地。 请你找出一个海洋单元格,这个海洋单元格

    2023-05-13:你现在手里有一份大小为 n x n 的 网格 grid, 上面的每个 单元格 都用 0 和 1 标记好了其中 0 代表海洋,1 代表陆地. 请你找出一个海洋单元格,这个海洋单元格 ...

  6. 原理一、Java中的HashMap的实现

    文章从JDK1.7和JDK1.8两个版本解析HashMap的实现原理及其中常见的面试题(两个版本HashMap最大的区别,1.7版HashMap=数组+链表,1.8版HashMap=数组+红黑树+链表 ...

  7. MySQL篇:第四章_详解DML语言

    DML语言 插入 一.方式一 语法: insert into 表名(字段名,...) values(值1,...); 特点: 1.字段类型和值类型一致或兼容,而且一一对应 2.可以为空的字段,可以不用 ...

  8. Python图像处理丨图像的灰度线性变换

    摘要:本文主要讲解灰度线性变换. 本文分享自华为云社区<[Python图像处理] 十五.图像的灰度线性变换>,作者:eastmount. 一.图像灰度线性变换原理 图像的灰度线性变换是通过 ...

  9. 如何在iPhone设备中查看崩溃日志

    ​ ​如何在iPhone设备中查看崩溃日志 目录 如何在iPhone设备中查看崩溃日志 摘要 引言 导致iPhone设备崩溃的主要原因是什么? 使用克魔助手查看iPhone设备中的崩溃日志 奔溃日志分 ...

  10. Axure 表格中根据条件设置不同的字体样式--中继器

    中继器+表格,根据条件设置不同的字体样式 思路:根据情形,设置不同的颜色,因为Axure 不能直接对元件的样式进行交互设置,所以借助[动态面板]进行设置 绘制表格详见:https://www.cnbl ...