当前位置: 首页 > news >正文

.NET Core中Emit的使用

反射允许我们在运行时获取对象的相关信息,创建对象的实例,执行方法。Emit是作为反射的一个比较高级的功能。使用Emit,可以从零开始动态的创建程序集及类。提供程序的灵活性。本文主要介绍.NET Core中Emit的使用。

1、程序集(Assembly)

程序集构成了 .NET 应用程序的部署、版本控制、重用、激活范围和安全权限的基本单元。 程序集是为协同工作而生成的类型和资源的集合,这些类型和资源构成了一个逻辑功能单元。 程序集采用可执行文件 (.exe) 或动态链接库文件 (.dll) 的形式,是 .NET 应用程序的构建基块 。 它们向公共语言运行时提供了注意类型实现代码所需的信息。在 .NET 和 .NET Framework 中,可从一个或多个源代码文件生成程序集。 在 .NET Framework 中,程序集可以包含一个或多个模块。使用System.Reflection.Emit可以动态创建程序集。

2、模块(Module)

模块是程序集内代码的逻辑集合,每个模块可以使用不同的语言编写,大多数情况下,一个程序集包含一个模块。程序集包括了代码、版本信息、元数据等。模块是没有 Assembly 清单的 Microsoft 中间语言(MSIL)文件。

3、Emit的使用

Emit可以使用MSIL指令动态编写程序逻辑,然后将指令编译成程序集。通过编写代码的方式动态创建程序。比如软件授权,可以输入授权信息后,生成一个授权的DLL,使用Emit实现动态AOP框架等。

1).NET Framework中使用Emit

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");}}
}

2).NET Core中使用Emit

using System;
using System.Reflection;
using System.Reflection.Emit;
namespace ConsoleApp2
{class Program{public static void Main(){AssemblyName aName = new AssemblyName("ChefDynamicAssembly");AssemblyBuilder ab =AssemblyBuilder.DefineDynamicAssembly(aName,AssemblyBuilderAccess.Run);ModuleBuilder mb = ab.DefineDynamicModule(aName.Name + ".dll");TypeBuilder tb = mb.DefineType("Commander");var attrs = MethodAttributes.Public;// 使用类型构建器创建一个方法构建器MethodBuilder methodBuilder = tb.DefineMethod("Do", attrs, typeof(string), Type.EmptyTypes);// 通过方法构建器获取一个MSIL生成器var IL = methodBuilder.GetILGenerator();// 开始编写方法的执行逻辑// var store = new string[3];var store = IL.DeclareLocal(typeof(string[]));IL.Emit(OpCodes.Ldc_I4, 3);IL.Emit(OpCodes.Newarr, typeof(string));IL.Emit(OpCodes.Stloc, store);//store[0] = "C"IL.Emit(OpCodes.Ldloc, store);IL.Emit(OpCodes.Ldc_I4, 0);IL.Emit(OpCodes.Ldstr, "C");IL.Emit(OpCodes.Stelem, typeof(string));//store[1] = "JAVA"IL.Emit(OpCodes.Ldloc, store);IL.Emit(OpCodes.Ldc_I4, 1);IL.Emit(OpCodes.Ldstr, "JAVA");IL.Emit(OpCodes.Stelem, typeof(string));//store[2] = "Python"IL.Emit(OpCodes.Ldloc, store);IL.Emit(OpCodes.Ldc_I4, 2);IL.Emit(OpCodes.Ldstr, "Python");IL.Emit(OpCodes.Stelem, typeof(string));// IChef chef = new GoodChef();var chef = IL.DeclareLocal(typeof(IChef));IL.Emit(OpCodes.Newobj, typeof(StoreChef).GetConstructor(Type.EmptyTypes));IL.Emit(OpCodes.Stloc, chef);//var dish = chef.Cook(vegetables);var dish = IL.DeclareLocal(typeof(string));IL.Emit(OpCodes.Ldloc, chef);IL.Emit(OpCodes.Ldloc, store);IL.Emit(OpCodes.Callvirt, typeof(IChef).GetMethod("Cook"));IL.Emit(OpCodes.Stloc, dish);// return dish;IL.Emit(OpCodes.Ldloc, dish);IL.Emit(OpCodes.Ret);//方法结束// 从类型构建器中创建出类型var dynamicType = tb.CreateType();// 通过反射创建出动态类型的实例var commander = Activator.CreateInstance(dynamicType);Console.WriteLine(dynamicType.GetMethod("Do").Invoke(commander, null).ToString());Console.ReadLine();}}public interface IChef{string Cook(string[] store);}public class StoreChef : IChef{public string Cook(string[] store){return "Value:" + string.Join("+", store);}}
}

相关文章:

  • windows如何查看自己的ip地址
  • React 中 react-i18next 切换语言( 项目国际化 )
  • 3Dexcite deltgen 2022x 新功能
  • (二)Pytorch快速搭建神经网络模型实现气温预测回归(代码+详细注解)
  • String字符串性能优化的几种方案
  • C++中类和动态内存分配
  • linux硬盘扩容
  • 十六、RabbitMQ快速入门
  • 开源更安全? yum源配置/rpm 什么是SSH?
  • Vue 2.0中引入的类型检查Flow
  • TypeError: expected np.ndarray (got Tensor)解决办法
  • 【机器学习基础】对数几率回归(logistic回归)
  • elementplus DateTimePicker 日期范围选择器 设置默认时间范围为当前月的起始时间到结束时间
  • pytorch下载离线包的网址
  • 设置指定时间之前的时间不可选
  • [deviceone开发]-do_Webview的基本示例
  • [LeetCode] Wiggle Sort
  • CentOS从零开始部署Nodejs项目
  • Computed property XXX was assigned to but it has no setter
  • idea + plantuml 画流程图
  • Java 23种设计模式 之单例模式 7种实现方式
  • java 多线程基础, 我觉得还是有必要看看的
  • js学习笔记
  • PHP那些事儿
  • SpiderData 2019年2月13日 DApp数据排行榜
  • vuex 学习笔记 01
  • 第2章 网络文档
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • ​​​​​​​Installing ROS on the Raspberry Pi
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • (4)事件处理——(7)简单事件(Simple events)
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (三分钟)速览传统边缘检测算子
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)编辑寄语:因为爱心,所以美丽
  • *上位机的定义
  • ..thread“main“ com.fasterxml.jackson.databind.JsonMappingException: Jackson version is too old 2.3.1
  • .gitignore文件设置了忽略但不生效
  • .NET 常见的偏门问题
  • .net 使用ajax控件后如何调用前端脚本
  • .Net 转战 Android 4.4 日常笔记(4)--按钮事件和国际化
  • .net(C#)中String.Format如何使用
  • .pub是什么文件_Rust 模块和文件 - 「译」
  • @Documented注解的作用
  • @RequestParam详解
  • [ C++ ] STL---string类的模拟实现
  • [ 数据结构 - C++] AVL树原理及实现
  • [22]. 括号生成
  • [BT]BUUCTF刷题第4天(3.22)
  • [bzoj4240] 有趣的家庭菜园
  • [C++][基础]1_变量、常量和基本类型
  • [corCTF 2022] CoRJail: From Null Byte Overflow To Docker Escape
  • [HNOI2008]Cards