Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write code to be executed BEFORE any method in an assembly?

Tags:

c#

.net

appdomain

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.

like image 687
moudrick Avatar asked Dec 20 '25 02:12

moudrick


2 Answers

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();
                }
            }
        }
like image 157
Francesco Baruchelli Avatar answered Dec 22 '25 14:12

Francesco Baruchelli


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.

like image 36
usr Avatar answered Dec 22 '25 14:12

usr