在过去的几年里,我偶尔会想,在.NET世界中可以使用著名的DLL_PROCESS_ATTACH
。(cctor),但你不能影响when it is called,也不能定义一个cctor,保证在任何其他cctor或字段初始化器之前被调用,如果该类从未被使用,则甚至根本不会调用它。
所以,如果你想保证在调用你的程序集的任何方法之前初始化某个东西,并且你不想在你的程序集中的每个类中添加一个cctor,你可以采取什么方法?或者在.NET中有一个简单的,托管的解决方案,我错过了这么多年?
在过去的几年里,我偶尔会想,在.NET世界中可以使用著名的DLL_PROCESS_ATTACH
。(cctor),但你不能影响when it is called,也不能定义一个cctor,保证在任何其他cctor或字段初始化器之前被调用,如果该类从未被使用,则甚至根本不会调用它。
所以,如果你想保证在调用你的程序集的任何方法之前初始化某个东西,并且你不想在你的程序集中的每个类中添加一个cctor,你可以采取什么方法?或者在.NET中有一个简单的,托管的解决方案,我错过了这么多年?
3条答案
按热度按时间1mrurvl11#
经过一些研究,我发现了this post by Microsoft,它解释了
DllMain
中混合托管和非托管代码的问题以及解决方案,这是第二版CLI,模块初始化器。这个初始化器刚好在本机DllMain之后运行(换句话说,在加载器锁之外),但在任何托管代码运行或从该模块访问托管数据之前。module .cctor的语义与class .cctors的语义非常相似,并且在ECMA C#和公共语言基础设施标准中定义。
虽然我在当前的ECMA规范中找不到术语 module initializer,但它在逻辑上是从 type initializer 和全局
<Module>
特殊类(见22.26节MethodDef,第40小节)而来的。此功能是在 * .NET 1.1之后实现的(即从2.0开始)。另请参阅this semi-official description。这个问题不是关于C#的,而是因为它是.NET的通用弗兰卡:C#不知道全局方法,你不能创建一个
<Module>
,更不用说它的cctor了。然而,Einar Egilsson有recognized this apparent deficiency,并创建了InjectModuleInitializer.exe,它允许你在Visual Studio中作为一个post/compile步骤来做这件事。在C++.NET中,使用这个方法是微不足道的,建议用这个方法来代替DllMain
。另见Ben Voigt的这个SO答案(不是公认的答案)和Yoyoyoyosef的这个SO答案。简而言之,module initializer 是在加载模块之后(不一定是在加载程序集的时候!)调用任何类或示例方法之前调用的第一个方法。它不接受参数,不返回值,但可以在其主体中包含任何托管代码。
pdsfdshx2#
实际上
cctor
并不是第一个被调用的,如果你有一个静态的字段被静态方法初始化,那么这个静态方法就会被调用。看看这个代码:
EDIT:也可以考虑使用Factory pattern,这将帮助您在返回创建的对象之前完成所有需要的初始化。
zphenhs43#
这是通过设计:它最小化了静态构造函数之间的耦合。你知道你的cctor将在你的类中的任何东西初始化之前被调用,并且在你的类使用的任何类的cctor之后被调用。但是与同一个应用程序中不相关的类相比,它不能保证什么时候运行。
如果你想确保你的一些代码在入口点之前运行,考虑为主应用程序编写一个 Package 器,一个直接的方法是把它放在一个单独的可执行文件中。
一个更独立的方法可以做到这一点:
1.以正确的顺序运行任何需要的启动代码。不要引用程序集中不应该初始化的任何类型。
1.创建您自己的应用程序域
1.在第二个应用程序域中运行真实的的入口点