There is an event AppDomain.CurrentDomain.DomainUnload which allows to clean up static resources which are independent of any particular instance of class and even of any particular class.
I consider it as the code which is executed AFTER any code in my current assembly (Am I right by the way?).
But is there a way to write a piece of code (for the current assembly) which is to be executed BEFORE any other code in the current assembly (class library)? Or should I look for a more tricky way to initialize some resources before any code started execution?
I know about static constructors, but the order of their calls is not well defined. In other words, there is no guarantee that a particular static constructor will be executed before other static constructors of other classes.
There is also an AppDomain.AssemblyLoad. I am not sure this is the thing I am looking for. This event occurs when OTHER assemblies are loaded, not the current.
I had the same problem and solved it this way.
I define an IAssembyInitializer interface with just the method void Initialize().
In every assembly for which I want to execute some code just after it is loaded, I define a class implementing this interface.
The I define an attribute to specify the classes in the assembly that implements this interface (otherwise you could find them out by Reflection, but I preferred it this way):
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class AssemblyInitializerAttribute : Attribute
{
AssemblyInitializerAttribute ()
{
}
AssemblyInitializerAttribute (string typeName)
{
TypeName = typeName;
}
public string TypeName;
}
The attribute is set in the AssemblyInfo in this way:
[assembly: AssemblyInitializerAttribute ("MyNamespace.AnAssemblyInitializer")]
Finally, in the main assembly of the application I register to the AssemblyLoad event a method that executes all the initializations:
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(NewAssemblyLoaded);
static void NewAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
{
Assembly anAssembly = args.LoadedAssembly;
AssemblyInitializerAttribute[] initializers = (AssemblyInitializerAttribute[])anAssembly .GetCustomAttributes(typeof(AssemblyInitializerAttribute), false);
foreach (AssemblyInitializerAttribute anInit in initializers)
{
Type initType = anInit.TypeName != null ? anAssembly.GetType(anInit.TypeName) : null;
if (initType != null && initType.GetInterface("IAssemblyInitializer") != null)
{
IAssemblyInitializer anInitializer = (IAssemblyInitializer)Activator.CreateInstance(initType);
anInitializer.Initialize();
}
}
}
You can use instances of Lazy<T> held in static fields to control static initialization order yourself. The code body of those Lazy<T> initializer objects can reference other Lazy<T> instances which automatically orchestrates a DAG of initialization. You cannot have cycles, obviously.
With C++/CLI you can indeed have code executed when the assembly loads (module initializers). You probably don't want to go that route.
With C# this is not possible. Static ctors and lazy initialization patterns are the best you get.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With