2009-02-02 110 views
32

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

如:

大会A不知道组件B,而B不知道A.大会A需要如果装载了B知道关于B某些事情。当运行时(引用或显式)加载程序集B时,我想要执行一段代码(静态方法或属性),调用程序集A中的方法。

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

回答

37

的CLR支持module initializers。你必须破解C++/CLI代码或ilasm.exe才能使用它们。

6

(编辑 - 适用于C#;对于C++的方法,请参阅this answer

基本上没有:你不能。这将是一个巨大的攻击面,并且不被允许。您可能希望将静态ctor放在某些B类型上,以确保执行init代码,但这是关于它的...

+5

为什么它是一个攻击面? – 2009-02-02 22:40:07

+1

这似乎很容易隐藏在那里没有代码明知地调用的代码 - 很难追踪,等等。更不要说哪个线程应该运行它的问题......也许我不能正确发声,但它听起来不明智。但它是没有意义的,因为你无法做到; -p – 2009-02-02 22:57:27

+0

你知道它是否有任何信息吗(模块初始化程序不在Load上运行,而是在静态构造函数之前运行),所以如果代码可以在加载期间运行。如果您检查是否可以回答这个非常接近的问题 - http://stackoverflow.com/questions/24718917/can-a-call-to-assembly-loadbyte-raise-the-appdomain-assemblyresolve-event/24719526? noredirect = 1#comment38423553_24719526 – 2014-07-15 16:50:55

3

您应该重新访问序列化方法以缓解此问题。如果您使用序列化和ISerializableSerializableAttribute属性,你可以把它使得串行图将加载程序集B在必要的时候没有一个装配有过明确了解装配B.

+0

如何使用此方法识别和加载组件B? – 2009-02-02 23:06:38

+0

如果序列化使用BinaryFormatter,那么实现ISerializable的序列化图中的任何类型将在反序列化过程中调用其构造函数,您可以在其中调用所需的任何代码。 因为当你序列化时,接口的序列化查询...... – 2009-02-02 23:11:50

5

你可以在.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

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

0

使用混合装配可以使DllMain在装配负载上运行。

3

有3个选项,以初始化一个.NET程序集:在你的大会

  1. 你写一个静态函数的init()或主()进行初始化,并从C#代码通过反射调用此函数加载此程序集。
  2. 编写一个托管的C++程序集,将代码放入DllMain()中。请小心,因为您的代码将在Loader Lock中执行,其中有几件事情是被禁止的(如加载其他DLL,...)。但是你可以开始一个新的线程来做任何初始化的东西。 (关于LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx)(关于 的DllMain: C# to C++/CLI to C DLL System.IO.FileNotFoundException
  3. 您编译纯C#大会和修改编译DLL添加一个模块初始化代码喜欢这里解释: http://einaregilsson.com/module-initializers-in-csharp/ 这种方法的缺点是,当程序集加载到进程中时,不会立即调用初始化函数。但是在程序集中的其他任何内容首次被访问之前调用它。