C#中的模块初始值设定项

模块初始值设定项是CLR的一项function,无法在C#或VB.NET中直接使用。 它们是名为.cctor全局静态方法,它们保证在执行程序.cctor任何其他代码(类型初始化程序,静态构造函数)之前运行。 我最近想在一个项目中使用它并使用Mono.Cecil 将我自己的解决方案(控制台程序/ msbuild任务)整合在一起,但我想知道:

  1. 有没有办法欺骗C#编译器发射模块初始化器? 任何属性(例如CompilerGenerated,SpecialName)或其他可以使用的技巧?

  2. 为了某些目的,C#/ VB.NET是否会自己发出这些初始化器? 从我所看到的它们被托管C ++用于某些互操作目的,但我找不到任何引用它们被用于其他目的。 有任何想法吗?

不,没有办法在C#中发出它们,因为C#将所有内容放在类/结构中,模块初始化器需要是全局的。

您将不得不使用不同的工具来编写它们,最好是IL-Assembler。

至于第二个问题,我不得不承认我不知道,但我从未见过任何由C#生成的,而且我经常使用ILDasm,所以我认为它不会发出它们。

查看由Simone Cropp编写的真棒开源IL-Weaver项目“ fody ”的模块初始化程序插件: https : //github.com/fody/moduleinit

它允许您指定一个方法,该方法将由fody转换为汇编初始值设定项:

 public static class ModuleInitializer { public static void Initialize() { //Init code } } 

得到这个:

 static () { ModuleInitializer.Initialize(); } 

也许System.Reflection.Emit命名空间可以帮助你。 MethodAttributes枚举包含类似的元素(SpecialName, RTSpecialName)

Einar,您的问题并没有告诉我您已经编写了一个工具,允许将模块初始化程序注入已编译的程序集中。

http://einaregilsson.com/module-initializers-in-csharp

我尝试了你的应用程序,它完美无缺。 在您编写时,它应该适用于从2到4.5的所有当前框架。

只有一个问题使您的解决方案对我无用:当应用程序首次访问程序集中的任何内容时,将调用初始化程序。

我需要的是,当程序集加载到进程中时,应立即调用模块初始化程序。 但事实并非如此。 因此,如果应用程序不访问程序集,它将永远不会被初始化。

在调查了一整天之后,在我看来,获得这个的唯一方法是编写一个托管C ++程序集并在DllMain()中执行代码。

如果你有静态构造函数或单例类,你可以访问true,静态变量C#编译器会发出.cctor。