0

0

C# 动态程序集生成方法 C#如何使用Reflection.Emit在运行时创建类型

幻夢星雲

幻夢星雲

发布时间:2026-02-01 10:05:36

|

417人浏览过

|

来源于php中文网

原创

必须先调用AssemblyBuilder.DefineDynamicAssembly,.NET 5+需用RunAndCollect或Run访问模式;TypeBuilder是定义动态类型的唯一入口,需手动声明字段、方法并用ILGenerator.Emit写IL指令,栈平衡与类型可见性须严格控制。

c# 动态程序集生成方法 c#如何使用reflection.emit在运行时创建类型

AssemblyBuilderModuleBuilder 构建可执行程序集

直接调用 AssemblyBuilder.DefineDynamicAssembly 是唯一能生成可运行类型的方式,不能跳过这一步。.NET 5+ 中必须使用 AssemblyBuilderAccess.RunAndCollect(推荐)或 Run,否则生成的类型无法被 JIT 编译执行。

常见错误是传入 AssemblyBuilderAccess.Save 后尝试实例化类型——此时类型只写入磁盘,未加载进当前上下文,Activator.CreateInstance 会抛出 FileNotFoundExceptionInvalidOperationException

  • 必须用 AssemblyLoadContext.Current.LoadFromStream() 手动加载 Save 模式生成的程序集,再反射创建实例
  • RunAndCollect 支持 GC 回收,但要求所有动态类型不被长期引用,否则影响卸载
  • 模块名(如 "MyModule.dll")只是标识符,不决定文件名;仅在 Save 模式下才实际写入磁盘

定义类时用 TypeBuilder 而不是 Class 关键字

TypeBuilder 是构建动态类型的唯一入口,它不继承任何已有类(除非显式调用 SetParent),默认基类是 object。字段、属性、方法都必须通过对应 Builder 添加,不能用 C# 语法糖。

典型陷阱:试图用 typeof(MyBaseClass).GetMethods() 获取虚方法再重写——不行。必须用 TypeBuilder.DefineMethod 显式定义,并调用 MethodBuilder.DefineParameterMethodBuilder.GetILGenerator() 填充逻辑。

  • 字段必须先用 TypeBuilder.DefineField 注册,才能在 IL 中用 OpCodes.Ldfld 访问
  • 自动属性无法自动生成 backing field,需手动定义字段 + 属性 getter/setter 方法
  • 泛型类型参数需通过 TypeBuilder.DefineGenericParameters 声明,且后续所有引用必须用 GenericTypeParameterBuilder

ILGenerator 写 IL 指令而不是 C# 代码

ILGenerator.Emit 系列方法是向方法体注入指令的唯一方式,没有“编译器帮你补全”这回事。比如返回一个整数,不能写 return 42;,而要:il.Emit(OpCodes.Ldc_I4, 42); il.Emit(OpCodes.Ret);

ClipDrop Relight
ClipDrop Relight

ClipDrop推出的AI图片图像打光工具

下载

最容易出错的是平衡:每条指令对求值栈有明确要求。例如 OpCodes.Call 需要栈顶已有匹配参数个数的对象/值,否则运行时报 InvalidProgramException,且堆栈无有效调试信息。

  • 调用实例方法前必须先 Emit(OpCodes.Ldarg_0)(this 引用)
  • 字符串字面量用 Ldstr,而非 Ldc_I4 加转换
  • 访问字段用 Ldfld/Stfld,访问属性必须调用其 get_*/set_* 方法
  • 局部变量需先 DeclareLocal,再用 Ldloc/Stloc 操作

动态类型在跨 Assembly 场景下的可见性问题

动态类型默认是 internal 级别,即使定义在 public 模块中,也无法被其他程序集访问。若需从外部调用(如插件系统),必须显式设为 public

typeBuilder.SetCustomAttribute(...); // 不够  
typeBuilder.SetAttributes(TypeAttributes.Public | TypeAttributes.Class);

更隐蔽的问题是:如果动态类型实现了某个接口,而该接口定义在另一个程序集中,必须确保该程序集已加载,且在 TypeBuilder.AddInterfaceImplementation 时传入的是已加载的 Type 对象,不能用字符串名称。

  • 接口类型必须来自 Assembly.GetType("IFoo") 或类似方式获取,否则 AddInterfaceImplementationArgumentException
  • 若接口含泛型参数,动态类型实现时需用 MakeGenericType 构造闭合类型
  • 动态类型无法被序列化(如 JSON.NET 默认拒绝),除非手动添加 [Serializable] 或实现 ISerializable

真正难的不是写对 IL,而是让动态类型和现有代码边界清晰、生命周期可控。比如热重载场景下,旧类型实例还在运行,新类型已生成,两者共存时的委托绑定、事件订阅、GC 回收时机,这些细节比 Emit 本身更消耗调试时间。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
json数据格式
json数据格式

JSON是一种轻量级的数据交换格式。本专题为大家带来json数据格式相关文章,帮助大家解决问题。

422

2023.08.07

json是什么
json是什么

JSON是一种轻量级的数据交换格式,具有简洁、易读、跨平台和语言的特点,JSON数据是通过键值对的方式进行组织,其中键是字符串,值可以是字符串、数值、布尔值、数组、对象或者null,在Web开发、数据交换和配置文件等方面得到广泛应用。本专题为大家提供json相关的文章、下载、课程内容,供大家免费下载体验。

536

2023.08.23

jquery怎么操作json
jquery怎么操作json

操作的方法有:1、“$.parseJSON(jsonString)”2、“$.getJSON(url, data, success)”;3、“$.each(obj, callback)”;4、“$.ajax()”。更多jquery怎么操作json的详细内容,可以访问本专题下面的文章。

313

2023.10.13

go语言处理json数据方法
go语言处理json数据方法

本专题整合了go语言中处理json数据方法,阅读专题下面的文章了解更多详细内容。

77

2025.09.10

mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

183

2023.12.04

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

289

2024.02.23

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

259

2025.06.11

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

126

2025.08.07

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

54

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.7万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号