views:

111

answers:

3

In the past years I've occasionally been wondering what equivalent of the (in)famous DLL_PROCESS_ATTACH was available in the .NET world. Any documentation I have says, slightly simplified, that the earliest entry point to a class is the static constructor (cctor), but you cannot influence when it is called, nor can you define one cctor that's guaranteed to be called prior to any other cctor or field initializer, hack, it may not even be called at all if the class is never used.

So, if you want to guarantee something's initialized before any method of your assembly is called and you don't want to have to add a cctor to every class in your assembly, what approach can you take? Or is there an easy, managed solution in .NET that I have missed all these years?

+1  A: 

This is by design: it minimises coupling between static constructors. You know that your cctor will be invoked before anything in your class initializes, and after the cctors of any classes used by your class. But there's no guarantee on when it will run compared to unrelated classes in the same application.

If you want to make sure some code of yours runs before the entry point, consider writing a wrapper for the main application. A straightforward way would be to put it in a separate executable.

A more self-contained way to do this might be to:

  1. Run whatever startup code is needed, in the right order. Don't reference any types in assemblies that shouldn't get initialized.
  2. Create your own app domain
  3. Run the real entry point within this second app domain
Tim Robinson
This is probably the path to take, I was afraid of this answer popping up. A separate executable, btw, will be of little use when your assembly is not an application per se, or is used in hosted environments (like ASP.NET).
Abel
+2  A: 

Actually it is not exactly true that cctor is called first. If you have static field initialized by static method that static method will be called.

Have a look at this code :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CallSequence
{
    internal class Test
    {
        internal Test()
        {
            Console.WriteLine("non-static constructor");
        }

        static Test()
        {
            Console.WriteLine("static constructor");
        }

        static int myField = InitMyField();

        static int InitMyField()
        {
            Console.WriteLine("static method : (InitMyField)");
            return 0;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Test t = new Test();
        }
    }
}

EDIT : Also consider using Factory pattern which will help you do all the needed initialization before returning created object.

Incognito
Apologies, my note *"(simplified)"*, which I had in my first version, was removed by me by accident. I know that static fields are initialized before the static cctor and that their order is not defined. That only makes for a stronger case for a method to be called before all this. Note: I edited my q. to reflect this apparent ambiguity, thanks for mentioning ;-)
Abel
Any answer on how to define *what* the earliest entrypoint is?
Abel
Earliest entry points are static initializers and constructor I am not sure is it what you need but it is possible that Factory pattern can be helpful if you need to do something like preinit.
Incognito
@Incognito, while your answer was interesting, it unfortunately wasn't what I was after. Maybe I worded my question wrongly, but have a look at my added answer, which is what I was looking for.
Abel
A: 

I'd normally not answer my own question, but meanwhile I did find an answer that hasn't come up here before, so here I go.

After some research, I happened on this post by Microsoft, which explains the problems of mixing managed and unmanaged code inside DllMain and the solution, which came about with the 2nd version of the CLI, module initializers. Quote:

This initializer runs just after the native DllMain (in other words, outside of loader lock) but before any managed code is run or managed data is accessed from that module. The semantics of the module .cctor are very similar to those of class .cctors and are defined in the ECMA C# and Common Language Infrastructure Standards.

While I wasn't able to find the term module initializer inside the current ECMA specification, it follows logically from type initializer and the global <Module> special class (see section 22.26 on MethodDef, sub-point 40). This feature was implemented after .NET 1.1 (i.e., from 2.0 onwards). See also this semi-official description.

This question wasn't about C#, but because it is the lingua franca of .NET: C# doesn't know global methods, and you can't create a <Module>, let alone its cctor. However, Einar Egilsson has recognized this apparent deficiency and created InjectModuleInitializer.exe that allows you to do this as a post/compile step from Visual Studio. In C++.NET, using this method is trivial and recommended practice in place of DllMain. See also this SO answer by Ben Voigt (not the accepted answer) and this SO answer by yoyoyoyosef.

In short, the module initializer is the first method that is called after loading the module (not necessarily when loading assembly!) and before calling any class or instance method. It takes no parameters, returns no value, but can contain any managed code in its body.

Abel