Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initialize library on Assembly load

I have a .net library dll that acts like a functional library. There are a bunch of static types along with static methods.

There is some initialization code that I need to run to set up the library ready for use.

When the assembly gets loaded is there a way to ensure that a particular method is run? Something like AppDomain.AssemblyLoad but called automatically from the assembly itself. I was thinking that maybe there is something like an AssemblyAttribute that could be used?

At the moment I have this initialization code in a static constructor but as this is a library with many entry points there is no guarantee that this particular type will be used.

Thanks!

like image 856
sixtowns Avatar asked Jan 19 '09 23:01

sixtowns


People also ask

When assembly will load on AppDomain?

If an assembly is loaded into the same AppDomain, then the class can be instantiated in the usual way. But if an assembly is loaded into a different AppDomain then it can be instantiated using reflection. Another way is an interface.

Can not load file or assembly?

In summary if you get the "Could not load file or assembly error", this means that either your projects or their references were built with a reference to a specific version of an assembly which is missing from your bin directory or GAC.

What is the method to load assembly given its file name and its path?

LoadFrom(String) Loads an assembly given its file name or path.


2 Answers

Yes there is - sort of.

Use the excellent little utility by by Einar Egilsson, InjectModuleInitializer.

Run this executable as a post build step to create a small .cctor function (the module initializer function) that calls a static void function of yours that takes no parameters. It would be nice if compiler gave us the ability to create .cctor(), luckily we rarely need this capability.

This is not a complete DllMain replacement, however. The CLR only calls this .cctor function prior to any methods called in your assembly, not upon assembly load. So, if you need something to happen upon assembly load, you need to have the loading code call a method directly or use the hack I detailed https://stackoverflow.com/a/9745422/240845

like image 148
mheyman Avatar answered Sep 19 '22 01:09

mheyman


The following solution is possible only when you have control over the main executing assembly, i.e. it's not suitable for standalone libraries meant for distribution

I've had a similar problem and solved it by creating an assembly-targeted attribute 'InitializeOnLoad' with a Type parameter. Then, in the main executable, I've added a trivial AppDomain.AssemblyLoaded handler, which scans the newly loaded assembly for the aforementioned attribute and calls System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor() on them.

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public class InitializeOnLoadAttribute : Attribute {     Type type;      public InitializeOnLoadAttribute(Type type) { this.type = type; }      public Type Type { get { return type; } } }  // somewhere very early in main exe initialization AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(AssemblyInitializer);  static void AssemblyInitializer(object sender, AssemblyLoadEventArgs args) {     // force static constructors in types specified by InitializeOnLoad     foreach (InitializeOnLoadAttribute attr in args.LoadedAssembly.GetCustomAttributes(typeof(InitializeOnLoadAttribute), false))         System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(attr.Type.TypeHandle); } 

additionaly, if you are afraid that assemblies might have been loade before you hook the AssemblyLoad event, you can simply run through AppDomain.GetAssemblies() and call the 'initializer' for them.

like image 32
Stefan Simek Avatar answered Sep 18 '22 01:09

Stefan Simek