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

时间:2021-09-23 03:06:16

Is it possible to run some code when an assembly is loaded, without doing anything specific in the loading code? What I am looking for is like a static constructor on a type.

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

Eg:

例如:

Assembly A does not know about Assembly B, but B does know about A. Assembly A needs to know certain things about B if B is loaded. When Assembly B is loaded by the runtime (referenced, or explicit), I want a piece of code (static method or attribute) to be executed that calls a method in Assembly A.

装配A不知道装配B,但是B知道装配A。如果装载B,装配A需要知道关于装配B的一些事情。当运行时(引用或显式)加载程序集B时,我希望执行调用程序集a中的方法的代码(静态方法或属性)。

The root cause of this problem is unknown types being encountered when serializing a type in A that contains types from B not known at compile time as interfaces are used.

这个问题的根本原因是当序列化a中的一个类型时遇到了未知类型,该类型包含在编译时不知道的B类型作为接口使用。

6 个解决方案

#1


38  

The CLR supports module initializers. You'd have to hack C++/CLI code or ilasm.exe to use them.

CLR支持模块初始化器。你必须破解c++ /CLI代码或ilasm。exe使用它们。

#2


6  

(edit - applies to C#; for a C++ approach, see this answer)

(编辑-适用于c#;对于c++方法,请参见此答案)

Basically, no: you can't. This would be a huge attack surface, and isn't allowed. You might want to put a static ctor on some of the B types that ensure the init code is executed, but that is about it...

基本上,不,你不能。这将是一个巨大的攻击面,是不允许的。您可能希望在某些类型的B上放置一个静态ctor,以确保执行init代码,但仅此而已……

#3


5  

You can use static constructors in .Net, but unfortunately they don't do what you want. Static constructors are only executed just before a type is used. See http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx for details.

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

You might get some mileage from subscribing to your AppDomain's AssemblyLoad event. See http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx.

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

In your event handler you could reflect on the newly loaded assembly, and get it to execute whatever code you like.

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

#4


4  

There are 3 options to initialize a .NET Assembly:

有3个选项可以初始化。net程序集:

  1. You write a static function Init() or Main() in your Assembly to be initialized and call this function by reflection from the C# code that loads this Assembly.
  2. 您可以在您的程序集中编写一个静态函数Init()或Main()来初始化,并通过加载该程序集的c#代码来调用这个函数。
  3. Write a Managed C++ Assembly where you put your code in DllMain(). Be careful because your code will be executed in the Loader Lock where several things are forbidden (like loading other DLL's,...). But you can start a new thread that does ANY initialization stuff. (About LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx) (About DllMain: C# to C++/CLI to C DLL System.IO.FileNotFoundException)
  4. 编写托管c++程序集,将代码放在DllMain()中。要小心,因为您的代码将在加载器锁中执行,在那里有一些事情是禁止的(比如加载其他DLL的…)。但是您可以启动一个执行任何初始化工作的新线程。(关于LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx)(关于DllMain: c# to c++ /CLI to C DLL System.IO.FileNotFoundException)
  5. You compile a pure C# Assembly and modify the compiled DLL to add a module initializer code like explained here: http://einaregilsson.com/module-initializers-in-csharp/ The disadvantage of this method is that the initialization function is not called immediately when the assembly is loaded into the process. But it is called before anything else in the assembly is first accessed.
  6. 您编译一个纯c#程序集并修改编译后的DLL来添加一个模块初始化代码,如下所示:http://einaregilsson.com/module- initializerin -csharp/此方法的缺点是,当程序集加载到进程中时,不会立即调用初始化函数。但是在第一次访问程序集中的其他内容之前调用它。

#5


3  

You should probably revisit your serialization approach to mitigate this problem. If you serialize using ISerializable and the SerializableAttribute attribute, you can make it such that the serialization graph will load assembly B when necessary without assembly A ever having to explicitly know about assembly B.

您可能应该重新考虑您的序列化方法来缓解这个问题。如果您使用ISerializable和SerializableAttribute属性进行序列化,那么可以使序列化图在必要时加载程序集B,而不需要程序集A显式地了解程序集B。

#6


0  

Using a mixed assembly you can get DllMain to run on an assembly load.

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

#1


38  

The CLR supports module initializers. You'd have to hack C++/CLI code or ilasm.exe to use them.

CLR支持模块初始化器。你必须破解c++ /CLI代码或ilasm。exe使用它们。

#2


6  

(edit - applies to C#; for a C++ approach, see this answer)

(编辑-适用于c#;对于c++方法,请参见此答案)

Basically, no: you can't. This would be a huge attack surface, and isn't allowed. You might want to put a static ctor on some of the B types that ensure the init code is executed, but that is about it...

基本上,不,你不能。这将是一个巨大的攻击面,是不允许的。您可能希望在某些类型的B上放置一个静态ctor,以确保执行init代码,但仅此而已……

#3


5  

You can use static constructors in .Net, but unfortunately they don't do what you want. Static constructors are only executed just before a type is used. See http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx for details.

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

You might get some mileage from subscribing to your AppDomain's AssemblyLoad event. See http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx.

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

In your event handler you could reflect on the newly loaded assembly, and get it to execute whatever code you like.

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

#4


4  

There are 3 options to initialize a .NET Assembly:

有3个选项可以初始化。net程序集:

  1. You write a static function Init() or Main() in your Assembly to be initialized and call this function by reflection from the C# code that loads this Assembly.
  2. 您可以在您的程序集中编写一个静态函数Init()或Main()来初始化,并通过加载该程序集的c#代码来调用这个函数。
  3. Write a Managed C++ Assembly where you put your code in DllMain(). Be careful because your code will be executed in the Loader Lock where several things are forbidden (like loading other DLL's,...). But you can start a new thread that does ANY initialization stuff. (About LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx) (About DllMain: C# to C++/CLI to C DLL System.IO.FileNotFoundException)
  4. 编写托管c++程序集,将代码放在DllMain()中。要小心,因为您的代码将在加载器锁中执行,在那里有一些事情是禁止的(比如加载其他DLL的…)。但是您可以启动一个执行任何初始化工作的新线程。(关于LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx)(关于DllMain: c# to c++ /CLI to C DLL System.IO.FileNotFoundException)
  5. You compile a pure C# Assembly and modify the compiled DLL to add a module initializer code like explained here: http://einaregilsson.com/module-initializers-in-csharp/ The disadvantage of this method is that the initialization function is not called immediately when the assembly is loaded into the process. But it is called before anything else in the assembly is first accessed.
  6. 您编译一个纯c#程序集并修改编译后的DLL来添加一个模块初始化代码,如下所示:http://einaregilsson.com/module- initializerin -csharp/此方法的缺点是,当程序集加载到进程中时,不会立即调用初始化函数。但是在第一次访问程序集中的其他内容之前调用它。

#5


3  

You should probably revisit your serialization approach to mitigate this problem. If you serialize using ISerializable and the SerializableAttribute attribute, you can make it such that the serialization graph will load assembly B when necessary without assembly A ever having to explicitly know about assembly B.

您可能应该重新考虑您的序列化方法来缓解这个问题。如果您使用ISerializable和SerializableAttribute属性进行序列化,那么可以使序列化图在必要时加载程序集B,而不需要程序集A显式地了解程序集B。

#6


0  

Using a mixed assembly you can get DllMain to run on an assembly load.

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