.Net:加载程序集时运行代码

问题描述 投票:0回答:6

是否可以在加载程序集时运行某些代码,而无需在加载代码中执行任何特定操作?我正在寻找的就像类型上的静态构造函数。

例如:

程序集 A 不了解程序集 B,但 B 确实了解 A。如果加载 B,则程序集 A 需要了解有关 B 的某些信息。当运行时(引用或显式)加载程序集 B 时,我希望执行一段调用程序集 A 中的方法的代码(静态方法或属性)。

此问题的根本原因是在序列化 A 中的类型时遇到未知类型,该类型包含 B 中由于使用接口而在编译时未知的类型。

.net wcf assemblies
6个回答
48
投票

CLR 支持模块初始值设定项。 您必须破解 C++/CLI 代码或 ilasm.exe 才能使用它们。

更新:自 .NET 5 起,通过 [ModuleInitializer] 属性在 C# 中直接支持


7
投票

您可以在.Net中使用静态构造函数,但不幸的是它们不能做您想要的事情。静态构造函数仅在使用类型之前执行。有关详细信息,请参阅 http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx

订阅 AppDomain 的 AssemblyLoad 事件可能会带来一些好处。请参阅 http://msdn.microsoft.com/en-us/library/system.appdomain. assemblyload.aspx

在事件处理程序中,您可以反映新加载的程序集,并让它执行您喜欢的任何代码。


7
投票

有 3 个选项可用于初始化 .NET 程序集:

  1. 您在要初始化的程序集中编写静态函数 Init() 或 Main(),并通过加载此程序集的 C# 代码反射来调用此函数。
  2. 编写一个托管 C++ 程序集,将代码放入 DllMain() 中。请小心,因为您的代码将在加载器锁中执行,其中禁止执行某些操作(例如加载其他 DLL,...)。但是您可以启动一个新线程来执行任何初始化操作。 (关于LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx)(关于 DLL主目录: C# 到 C++/CLI 到 C DLL System.IO.FileNotFoundException)
  3. 您编译一个纯 C# 程序集并修改编译的 DLL 以添加模块初始值设定项代码,如下所述: http://einaregilsson.com/module-initializers-in-csharp/ 这种方法的缺点是当程序集加载到进程中时,不会立即调用初始化函数。但它是在首次访问程序集中的其他任何内容之前调用的。

6
投票

(编辑 - 适用于 C#;有关 C++ 方法,请参阅 此答案

基本上,不:你不能。这将是一个巨大的攻击面,并且是不允许的。您可能想在某些 B 类型上放置一个静态构造函数,以确保执行初始化代码,但仅此而已......


3
投票

您可能应该重新审视您的序列化方法来缓解这个问题。如果使用

ISerializable
SerializableAttribute
属性进行序列化,则可以使序列化图在必要时加载程序集 B,而程序集 A 无需显式了解程序集 B。


0
投票

使用混合程序集,您可以让 DllMain 在程序集加载上运行。

© www.soinside.com 2019 - 2024. All rights reserved.