Question

Module initializers are a feature of the CLR that are not directly available in C# or VB.NET. They are global static methods named .cctor that are guaranteed to run before any other code (type initializers, static constructors) in an assembly are executed. I recently wanted to use this in a project and hacked together my own solution (console program/msbuild task) using Mono.Cecil, but I was wondering:

  1. Is there any way to trick the C# compiler into emitting module intializers? Any attributes (e.g. CompilerGenerated, SpecialName) or other trickery that could be used?

  2. Do the C# / VB.NET ever emit these initializers themselves for some purpose? From what I've seen they are used by managed C++ for some interop purposes, but I couldn't find any reference to them being used for other purposes. Any ideas?

Was it helpful?

Solution

No, there is no way to emit them in C#, because C# puts everything in a class/struct and module initializers need to be global.

You will have to use a different tool to write them, preferably IL-Assembler.

As for the second question, I have to admit that I don't know, but I have never seen any generated by C#, and I use ILDasm quite often, so I assume that it doesn't emit them.

OTHER TIPS

Check out the module initializer addon of the awesome opensource IL-Weaver project "fody", written by Simon Cropp: https://github.com/fody/moduleinit

It allows you to specify a method which will be translated into an assembly initializer by fody:

public static class ModuleInitializer
{
    public static void Initialize()
    {
        //Init code
    }
}

gets this:

static <Module>()
{
    ModuleInitializer.Initialize();
}

Maybe System.Reflection.Emit namespace can help you. MethodAttributes enumeration contains similar elements (SpecialName, RTSpecialName).

Einar, Your question did not make clear to me that you already wrote a tool that allows to inject a module initializer into an already compiled Assembly.

http://einaregilsson.com/module-initializers-in-csharp

I tried your application and it works perfectly. As you write it should work with all current frameworks from 2 to 4.5.

There is only one problem that makes your solution useless for me: Your initializer is called when the application first ACCESSES anything in the assembly.

What I need is that the module initializer should be called immediately when the Assembly is loaded into the process. But it is not. So if the application does not access the assembly it will never be initialized.

After investigating a whole day it seems to me that the only way to get this is to write a Managed C++ Assembly and execute the code in DllMain().

If you have static constructors or singleton classes which you can access true a static variable C# compiler will emit .cctor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top