模块初始值设定项是CLR的一项功能,无法在C#或VB.NET中直接使用.它们是名为的全局静态方法.cctor,保证在执行程序集中的任何其他代码(类型初始化程序,静态构造函数)之前运行.我最近想在一个项目中使用它并使用Mono.Cecil 将我自己的解决方案(控制台程序/ msbuild任务)一起攻击,但我想知道:
有没有办法欺骗C#编译器发射模块初始化器?任何属性(例如CompilerGenerated,SpecialName)或其他可以使用的技巧?
C#/ VB.NET是否会出于某种目的自己发出这些初始化器?从我所看到的它们被托管C++用于某些互操作目的,但我找不到任何引用它们用于其他目的.有任何想法吗?
是否可以为 c++/cli 动态库运行托管初始化代码?我有大量托管类,所有托管类都包装了底层非托管功能,供许多不同的解决方案使用。我现在需要在执行其他任何操作之前调用一些托管代码,并且我已经尝试了几次尝试但尚未成功。
我最初尝试在 DllMain 函数中运行代码,但很快意识到不能在 DllMain 中调用托管代码,因为它不安全并且会发生 LoaderLock。然后我发现我可以编写自己的模块构造函数,如下所示:
#pragma warning( disable : 4483 )
void __clrcall __identifier(".cctor")()
{
// Do managed code initialisation here
}
Run Code Online (Sandbox Code Playgroud)
但是,这似乎覆盖了默认的模块构造函数,并且我收到很多链接器警告,例如:
warning LNK4210: .CRTMP section exists; there may be unhandled static initializers or terminators
Run Code Online (Sandbox Code Playgroud)
一些研究表明,默认模块构造函数 _DllMainCRTStartup 调用 _CRT_INIT,它初始化 C/C++ 静态对象。普遍的共识似乎是覆盖 dll 的入口点是一个非常糟糕的主意,而且我不想给自己带来更多问题。
我尝试的最后一件事是在全局范围内创建托管初始化程序类的全局静态对象,希望它可以在 _CRT_INIT 内部初始化,但情况似乎并非如此。
有什么方法可以执行一些托管代码作为模块初始化,甚至执行仍然保证在模块中的其他任何内容之前被调用的延迟代码?
谢谢,目前我依赖于提供在应用程序级别调用的静态初始化函数,但我显然不能强制该库的所有用户在其应用程序中执行此操作。我看到的另一个选项是在所有托管类构造函数中添加初始化调用,但同样,我无法确定在此库上构建的任何人都会遵循相同的设计模式,并且似乎需要维护很多内容,特别是如果有的话是进行 CLR 模块初始化的简单方法。