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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/153798.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue项目Jenkins自动化部署

1. 需求描述 我们希望提交uat分支时,UAT项目能够自动发布,提交master分支时,无需自动发布,管理员手工发布 2. 效果展示 3. 采用技术 Jenkins + K8S + Docker + Nginx 4. 具体实现 4.1 编写default.conf 在Vue项目根目录新建default.conf文件,主要进行代理配置、首页…

一个模板承包你所有表情包!

深度学习自然语言处理 原创作者:cola meme是一种现代的交流形式,其模板具有基本的语义,任何人都可以在社交媒体上发布它。由于机器学习系统没有足够的上下文来理解meme,因为它比图像和文本有更丰富的内容,所以机器学习…

如何通过数环通,让企业吸引和留住更多优秀人才?

企业招聘员工以及员工入职,不仅仅只是人力资源重要职能之一,它们更是整个企业成功的关键。 市场永远充满竞争,“战争”一直都在,为了赢得胜利,让最优秀的人选加入是最好的选择。但优秀的人才永远不缺机会,市…

EDIFACT学习手册

EDIFACT 又名 UN/EDIFACT(全称为 United Nations/Electronic Data Interchange For Administration, Commerce and Transport),是由联合国主导开发制定的国际通用 EDI 标准。EDI术语中的EDIFACT是指 EDIFACT 报文标准,本视频将为大…

gpio-export配置默认gpio

gpio-export配置默认gpio 用于设置gpio的默认状态和导出用户空间借口。只需要在设备树中配置节点即可。 参考链接: https://linux-arm-kernel.infradead.narkive.com/QRDUydDE/patch-0-2-gpio-allow-userspace-export-from-dt#post9 https://devicetree.vger.ke…

虚拟机配置centos7网络

一、编辑虚拟网络 二、编辑 ifcfg-ens32 配置静态ip vim /etc/sysconfig/network-scripts/ifcfg-ens32 三、网卡设置 四、重启网络 systemctl restart network

【外汇天眼】投资之道:成功背后的频繁交易陷阱

成功的投资需要超越人性的短板,其中之一就是频繁交易。巴菲特曾明言,如果商学院的毕业生在毕业后拿一张卡片,每买一支股票就打一个洞,那么这张卡片最终会被打得最少的人将成为巨富。“钱在这里从活跃的投资者流向有耐心的投资者。…

Android: ListView + ArrayAdapter 简单应用

​​容器与适配器&#xff1a;​​​​​ http://t.csdnimg.cn/ZfAJ7 activity_main.xml <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:app"h…

linux内核管理

linux内核会占用一定的空间&#xff0c;所以可以清理一下不需要使用的内核. 参考链接 Linux 内核及其关联文件通常存储在 /boot 目录下&#xff0c;内核模块通常存储在 /lib/modules 目录中。 首先查看已安装的列表&#xff1a; dpkg --list | grep linux-image其中&#xff…

2023年中国聚氨酯树脂涂料需求量、市场规模及行业趋势分析[图]

聚氨酯是一种新兴的有机高分子材料&#xff0c;被誉为“第五大塑料”&#xff0c;因其卓越的性能而被广泛应用于国民经济众多领域。产品应用领域涉及轻工、化工、电子、纺织、医疗、建筑、建材、汽车、国防、航天、航空等。2022年中国聚氨酯产量已达1600万吨。 2012-2022年中国…

为什么几乎所有的量化交易都用Python?

因为python好用啊&#xff01;Python&#xff0c;作为一种功能强大且易于学习的编程语言&#xff0c;已经成为金融分析师的首选工具。 以下我将从3个方面给大家分析python为何成为量化交易的理想选择。 一、语言特性与金融分析的匹配性 1、简单易懂的语言 Python就像我们的日…

传统Office太占存储空间?快来试试这款LiberOffice

用过Microsoft Office的同学&#xff0c;在完成安装后会发现MS Office系列的软件所占内存还是不小的&#xff0c;尤其当你组件下载很多以后&#xff0c;存储量真不是一个小数目。 那么&#xff0c;有没有一款轻量级的办公软件呢&#xff1f;别着急&#xff0c;今天学长就带来这…

【vue2】前端如何播放rtsp 视频流,拿到rtsp视频流地址如何处理,海康视频rtsp h264 如何播放

文章目录 测试以vue2 为例新建 webrtcstreamer.js下载webrtc-streamervideo.vue页面中调用 最近在写vue2 项目其中有个需求是实时播放摄像头的视频&#xff0c;摄像头是 海康的设备&#xff0c;搞了很长时间终于监控视频出来了&#xff0c;记录一下&#xff0c;放置下次遇到。…

传统考勤太复杂怎么办?这个小技巧,我必须吹爆!

随着科技的不断进步&#xff0c;人脸识别技术在各个领域得到了广泛的应用。在企业管理和安全领域&#xff0c;三维人脸考勤系统成为了一种高效、准确的管理工具。 客户案例 银行 天津某银行是一家金融机构&#xff0c;对于安全性要求极高。传统的考勤系统无法满足他们对于员工…

08_面向对象高级_枚举

枚举 1. 认识枚举 枚举是一种特殊的类。 public class Test {public static void main(String[] args) {A objX A.X;System.out.println(objX); // X} }enum A {// 注意&#xff0c;枚举类的第一行必须罗列枚举对象的名称X,Y,Z;private String name;public String getName…

在 Linux 和 Windows 系统下查看 CUDA 和 cuDNN 版本的方法,包括使用 nvcc 命令

一直都比较头疼cuda与cudnn版本查看问题&#xff0c;两个系统不一样也不好查看&#xff0c;命令不通用 Linux 查看 CUDA 版本 方法一&#xff1a; nvcc --version或 nvcc -V如果 nvcc 没有安装&#xff0c;那么用方法二。 方法二&#xff1a; 去安装目录下查看&#xff…

ip地址跟wifi有关系吗

​你可能已经听说过IP地址和Wi-Fi这两个词&#xff0c;但你有没有想过它们之间是否有关系呢&#xff1f;在这篇文章中&#xff0c;我们将深入探讨IP地址与Wi-Fi之间的密切联系。从基本概念到应用实例&#xff0c;虎观代理小二二将为您解答这个问题。 首先&#xff0c;让我们来了…

Threejs_08 纹理颜色的调整(颜色空间的设置)

为什么写入的贴图颜色跟实际的颜色有差别呢&#xff1f; 具体为啥我也不知道&#xff0c;总之就是threejs有两个颜色空间 一个是线性的 一个是rgb那种样式的&#xff0c;但是人眼对光照强度的感知并不是线性的&#xff0c;所以threejs的默认属性&#xff0c;到人眼中&#xff…

存储区域网络(SAN)之FC-SAN和IP-SAN的比较

存储区域网络(Storage Area Network&#xff0c;SAN)用于将多个系统连接到存储设备和子系统。 早期FC-SAN&#xff1a; 采用光纤通道(Fibre Channel&#xff0c;FC)技术&#xff0c;通过光纤通道交换机连接存储阵列和服务器主机&#xff0c;建立专用于数据存储的区域网络。 传…