Abe*_*bel 5 .net c# assemblies static-constructor entry-point
在过去的几年里,我偶尔想知道DLL_PROCESS_ATTACH.NET 世界中有什么与(臭名昭著)著名的东西相当的东西。我所拥有的任何文档都说,稍微简化一下,类的最早入口点是静态构造函数(cctor),但是您不能影响它的调用时间,也不能定义一个保证在任何其他 cctor 之前调用的 cctor或者字段初始值设定项、hack,如果从未使用过该类,甚至可能根本不会调用它。
因此,如果您想保证在调用程序集的任何方法之前初始化某些内容,并且您不想向程序集中的每个类添加一个 cctor,那么您可以采取什么方法?或者 .NET 中是否有一个我多年来一直怀念的简单的托管解决方案?
我通常不会回答自己的问题,但同时我确实找到了以前没有出现过的答案,所以我就开始吧。
经过一番研究,我偶然发现了Microsoft 的这篇文章,它解释了内部混合托管和非托管代码的问题DllMain以及解决方案,该解决方案是由 CLI 的第二个版本(模块初始化程序)提供的。引用:
此初始化程序在本机 DllMain 之后(换句话说,在加载程序锁之外)运行,但在运行任何托管代码或从该模块访问托管数据之前运行。模块 .cctor 的语义与类 .cctors 的语义非常相似,并且在 ECMA C# 和公共语言基础结构标准中定义。
虽然我无法在当前 ECMA 规范中找到术语“模块初始值设定项” ,但它在逻辑上遵循类型初始值设定项和全局<Module>特殊类(请参阅有关 MethodDef 的第 22.26 节,子点 40)。该功能是在.NET 1.1之后(即从2.0开始)实现的。另请参阅此半官方描述。
这个问题与 C# 无关,而是因为它是 .NET 的通用语言:C# 不知道全局方法,并且您无法创建<Module>,更不用说它的 cctor 了。然而,Einar Egilsson 已经认识到这一明显的缺陷,并创建了 InjectModuleInitializer.exe,它允许您从 Visual Studio 作为后/编译步骤来执行此操作。在 C++.NET 中,使用此方法很简单,建议代替DllMain. 另请参阅Ben Voigt 的此 SO 答案(不是已接受的答案)和yoyoyoyosef 的此 SO 答案。
简而言之,模块初始值设定项是在加载模块之后(不一定是在加载程序集时!)并且在调用任何类或实例方法之前调用的第一个方法。它不接受参数,不返回值,但可以在其主体中包含任何托管代码。
| 归档时间: |
|
| 查看次数: |
1777 次 |
| 最近记录: |