给旧版 .NET 也开一扇“私有之门”——ILAccess.Fody 实现原理与设计

news/2025/10/31 14:19:48/文章来源:https://www.cnblogs.com/huoshan12345/p/19179723

给旧版 .NET 也开一扇"私有之门" —— ILAccess.Fody 实现原理与设计

作者:huoshan12345
项目地址:ILAccess.Fody


前言:从 UnsafeAccessor 说起

在 .NET 8 中, 微软引入了一个让底层开发者非常心动的新特性 —— UnsafeAccessor
它允许我们在不使用反射的情况下访问类的私有字段、方法或构造函数, 而且是强类型零开销的.

举个例子:

class Dog
{private string _name = "Puppy";
}static class DogAccessors
{[UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_name")]public static extern ref string GetName(Dog d);
}var dog = new Dog();
ref var name = ref DogAccessors.GetName(dog);
Console.WriteLine(name); // Puppy

CLR 会在运行时将 GetName 绑定到 _name 字段, 生成直接访问的 IL 指令.性能几乎和直接访问公有字段相当.

🧩 Benchmark(来自 Sharmila Malar 的 Medium 文章)

  • Reflection: ~10.9 ns
  • UnsafeAccessor: ~1.99 ns
  • Direct Access: ~1.81 ns

但是, 这个特性只在 .NET 8+ 可用.


ILAccess.Fody 诞生

我希望旧版 .NET 平台(例如 .NET Framework、.NET Standard、.NET 6)也能享受这种“反射级灵活 + 原生级性能”的能力.于是我编写了 ILAccess.Fody. 它实现了和 UnsafeAccessor 几乎一致的语法和体验, 但通过 Fody + Mono.Cecil 在编译期修改 IL 来实现.

  • Mono.Cecil 是一个用于分析和修改 .NET 程序集的库, 它提供了强大的对象模型, 让我们能在不加载程序集的情况下读取、编辑、甚至生成新的 IL 代码.
  • Fody 是一个基于 Mono.Cecil 可扩展的编译期织入工具, 它让开发者能在构建过程中直接修改程序集的 IL, 而无需手动处理 MSBuild 或 Visual Studio 的复杂管线.

使用方法 (和UnsafeAccessor几乎一样)

static class DogILAccessors
{// UnsafeAccessorAttribute -> ILAccessorAttribute// UnsafeAccessorKind -> ILAccessorKind[ILAccessor(ILAccessorKind.Field, Name = "_name")]public static extern ref string GetName(Dog d);
}var dog = new Dog();
ref var name = ref DogILAccessors.GetName(dog);
Console.WriteLine(name); // Puppy

编译后, ILAccess.Fody 会将这些标记了 ILAccessor 的桩方法体替换为直接访问私有成员的 IL :

.method public hidebysig static string& GetName(class ILAccess.Dog d) cil managed
{IL_0000: ldarg.0      // dIL_0001: ldflda       string ILAccess.Dog::_nameIL_0006: ret
}

没有反射、没有委托、没有运行时查找.


核心实现: 编译期注入 IL

  • 遍历所有方法, 找到带 [ILAccessor] 的桩方法.
  • 根据不同的 ILAccessorKind 生成对应的 IL 指令.
  • 确定目标类型, 对于构造函数目标类型就是桩方法的返回类型, 其余的就是桩方法的第一个参数的类型.
  • 对于字段, 根据字段名匹配, 在目标类型的声明字段里找到目标字段, 然后根据是否为静态选择 LdsfldLdfld 指令, 如果是 ref访问, 则需选择 LdsfldaLdfld
  • 对于方法, 则需要根据方法名+泛型参数个数+参数类型列表来匹配, 在目标类型的声明方法里找到目标方法, 然后选择 callvirtcall 指令
  • 对于构造函数, 其实就是一个名为 .ctor 的方法, 处理方式和普通方法类似, 不过指令是 newobj

额外处理

  • 当想访问的私有成员的类型是定义在一个 引用程序集(Reference Assemblies) 中

比如想访问基础库中的 List<T>_items, 而基础库在编译时通常会以 引用程序集 的形式进行引用, 此时这个程序集只包含这个类型的公共成员的定义, 不包括其实现已经所A有的私有成员. 那么就无法根据名称找到私有成员的用于生成 IL 的元数据.
解决方法: 先通过引用程序集的路径找到其对应的 实现程序集(Implementation Assemblies) 的路径, 并从其中读取所需的元数据.

  • 当想访问的私有成员的类型并不定义在当前被编译的程序集中

这种情况如果直接使用 IL 指令访问其私有成员会触发 MethodAccessException 或者 FieldAccessException 之类的异常.
解决方法: 使用 IgnoresAccessChecksToAttribute 跳过对想访问的程序集的权限检查. 例如

[assembly: IgnoresAccessChecksTo("System.Private.CoreLib")] // 跳过对基础库的访问检查

不过在使用 ILAccess.Fody 的时候无需手动添加这些代码, 它会自动生成并注入到被编译的程序集中.


访问私有成员方法的对比

特性 反射 UnsafeAccessor ILAccess.Fody
支持平台 所有 .NET 平台 仅 .NET 8+ 全部 .NET 平台
实现方式 运行时查找 CLR 运行时注入 Fody 编译期注入
性能 几乎接近直接访问 几乎接近直接访问
编译期验证
AOT支持 ⚠️ 受限支持

结语

ILAccess.Fody 的目标很纯粹:

让旧版 .NET 也能拥有 UnsafeAccessor 的力量.

它用编译期 IL 注入的方式, 让私有访问变得强大而安全.
如果你想了解更多, 欢迎访问: 👉 ILAccess.Fody

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

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

相关文章

当Dify遇见Selenium:可视化编排UI自动化测试,原来如此简单

关注 霍格沃兹测试学院公众号,回复「资料」, 领取人工智能测试开发技术合集 在UI自动化测试领域,Selenium一直是无可争议的王者,但其陡峭的学习曲线和复杂的代码维护成本让许多测试团队望而却步。而今,通过Dify的可…

Playwright与Selenium的对比

明白了!既然你有 Python 和 Selenium 的基础,那学习 Playwright 会非常快。我们来用你熟悉的视角来讲解。Playwright vs Selenium:程序员视角 把它们都看作是 "浏览器遥控器",但 Playwright 是新一代的、…

MLGO微算法科技发布多用户协同推理批处理优化系统,重构AI推理服务效率与能耗新标准

在人工智能(AI)与移动计算深度融合的背景下,边缘计算逐步成为新一代智能服务基础架构的核心。在这一浪潮中,微算法科技(NASDAQ:MLGO)推出一种具有批处理功能的边缘服务器实现多用户协同推理技术,这项技术不仅提…

2025 年 HDPE 土工膜,聚乙烯土工膜,糙面土工膜厂家最新推荐,产能、专利、环保三维数据透视!

引言 在基建与环保工程需求激增的背景下,HDPE、聚乙烯、糙面土工膜的市场规模持续扩大,但产品质量差异显著,行业抽检显示仅有 68% 的产品核心指标达标。为破解采购困境,本次推荐依托土工合成材料工程协会 2025 年度…

2025年汽油发电机生产厂家权威推荐榜单:静音发电机/施工发电机/高原发电机源头厂家精选

根据QYR(QYResearch)的统计及预测,2024年全球汽油发电机市场销售额已达到9.71亿美元,预计到2031年将增长至13.42亿美元,期间年复合增长率(CAGR)为4.8%。全球市场目前呈现高度集中态势,前三大厂商合计占据超过3…

泛微ecology-9流程功能的后续-流程明细导出

泛微ecology9的OA流程明细导出流程明细导出功能 以前的认知 故事背景 泛微e9的流程明细导出功能缺失 默认一直有一个明细导入功能,之前在泛微做运维的时候经常有客户咨询:“为什么没有明细导出功能” 泛微总部技术同…

Core loss in maxwell

Core loss in maxwell2025-10-31 14:10 斑鸠,一生。 阅读(0) 评论(0) 收藏 举报 一、计算方式二、Example 三、涡流场与瞬态场中磁滞损耗的对比

西部数据MyCloud NAS漏洞分析与技术揭秘

本文详细分析了西部数据MyCloud NAS设备中的多个安全漏洞,包括登录绕过漏洞、命令注入漏洞和任意文件上传漏洞,涉及PHP代码审计、shell命令注入等技术细节,揭示了该系列设备存在的严重安全问题。西部数据MyCloud NA…

Claude Skill官方仓库Skill解析

📋 概述 Claude Code Skill官方仓库地址 本文档提供了Claude Skills仓库的完整目录结构和详细说明。该仓库包含18个技能,分为两大类:专有文档处理技能和开源示例技能。📁 根目录结构 skills-main/ ├── .claud…

2025年深圳市场调研机构权威推荐榜单:市场执行/市场调查/神秘顾客源头机构精选

在深圳产业升级与数字化转型的浪潮下,2025年深圳及周边地区的市场调研需求同比增长超20%,企业对数据驱动的决策依赖度提高了35%。精准、客观的市场洞察已成为企业制定战略的关键依据。 为帮助各类企业精准筛选合格供…

2025年乌鲁木齐黄金回收权威推荐榜单:黄金上门回收/黄金首饰回收/黄金首饰加工服务商精选

随着黄金价格的持续波动与消费者对资产流动性的需求增长,乌鲁木齐黄金回收市场正逐步向规范化、专业化、透明化方向发展。黄金回收服务涵盖金条、金饰、K金、钻石、名表、名酒等多类贵重物品,涉及重量鉴定、成色检测…

The lifelong path of human

So what’s my lifelong path? I’m a software engineer, a professor, a Chinese, English, or other else? Can I have all of the occupations? Should I have all of the occupations? Are people REALLY fre…

高压氧舱服务商推荐:探索2025年最佳服务选择,提升健康生活品质

摘要 高压氧舱行业在2025年迎来快速发展,广泛应用于健康改善、疾病辅助治疗和抗衰老领域。本文基于市场调研和用户反馈,推荐前十家高压氧舱服务商,并提供详细比较,帮助用户做出明智选择。表单内容仅供参考,实际选…

2025年郑州除甲醛公司权威推荐榜单:氧道净醛水漆/新房装修除甲醛/甲醛净化服务商精选

随着公众健康意识的提升和装修污染的普遍存在,郑州除甲醛市场正迎来专业化、技术化的发展阶段。室内空气质量不仅关系到居住舒适度,更直接影响人体健康。本文将基于企业资质、技术实力、产品性能、服务案例及客户反馈…

2025年10月人形机器人落地商排名榜:赛飞特工程技术集团赋能榜

人形机器人赛道在2025年迎来“场景落地”大考。工信部《人形机器人创新发展指导意见》与10月刚发布的《中国人形机器人产业白皮书》共同指出:2025—2027年是规模化落地的窗口期,但“技术先进却落地困难”仍是最大堵点…

2025 年健身器材品牌最新推荐榜,技术实力与市场口碑深度解析单位 / 家庭 / 有氧 / 力量健身器材推荐

引言 2025 年健身器材行业迎来新国标全面实施元年,《室外健身器材的安全 通用要求》(GB19272)等标准推动行业向安全化、智能化升级。为破解市场同质化与质量参差问题,本次推荐榜依托体育用品业联合会测评体系,结合…

设计师必看!PS 2026 解锁 AI 修图新玩法:第三方模型 + 实时协作 + 显卡专属加速,效率直接拉满

Adobe Photoshop 2026 v27.0正式发布,以创新功能与极致性能,重新定义专业修图体验。视觉层面采用简洁灵动的设计风格,开启编辑工作即能感受到新鲜活力;功能层面,两大新工具 ——移除工具与AI 查找干扰功能重磅上线…

四大主流平台深度测评:2025 企业自动化运维平台选型指南,自动化巡检平台适配核心场景

2025年企业IT运维面临资源异构及场景聚合分散的矛盾,自动化运维平台成为核心基建。选型需兼顾场景化与平台化,文章对比主流自动化运维系统,从核心定位、关键能力、适配场景全方位剖析,为企业选型提供依据,强调需贴…

如何编译一个Java 文件?

如何编译一个Java 文件?编译 Java 文件需要使用 JDK(Java Development Kit)提供的javac命令。以下是详细的编译步骤和相关说明: 一、编译前的准备安装 JDK 并配置环境变量确保已安装 JDK(而非仅 JRE),并正确配置…