Search code examples
c#.netstatic-constructortypeinitializer

How do I explicitly run the static constructor of an unknown type?


Possible Duplicate:
How do I invoke a static constructor with reflection?

I've got some initialization code in the static constructor of various classes. I can't create instances, nor do I know the types in advance. I would like to ensure the classes are loaded.

I tried this:

fooType.TypeInitializer.Invoke (new object[0]);

But got a MemberAccessException: Type initializer was not callable.

I'm assuming this is because the cctor is private? Is there a way to fix this without changing the architecture?

Edit: I found a workaround using RuntimeHelpers.RunClassConstructor, but this way seems to be barely documented in the MSDN and I'm not sure if it is a hack or a reasonable, prod system like way.


Solution

  • I'm not sure why this works, but as far as I reason (with help from Skeet) if i have a static class

    public static class Statics1
    {
        public static string Value1 { get; set; }
    
        static Statics1()
        {
            Console.WriteLine("Statics1 cctor");
            Value1 = "Initialized 1";
        }
    }
    

    The code:

    Type staticType = typeof (Statics1);
    staticType.TypeInitializer.Invoke(null);
    or
    staticType.TypeInitializer.Invoke(new object[0]);
    

    will throw with an exception, because somehow this resolves to the .ctor, instead of the .cctor of the class.
    If I use an explicitly static class, it is treated like an abstract sealed class, so the exception is that an abstract class cannot be instantiated, and if I use a regular class with a static constructor, the exception is that the type initializer is not callable.

    But if I use the Invoke overload with two parameters (instance, params), like this:

    Type staticType = typeof (Statics1);
    staticType.TypeInitializer.Invoke(null, null);
    

    explicitly stating that I am invoking a static method (that's the meaning of the first null - no instance == static), this works and initializes the class.


    That said, static constructors are strange beasts. Invoking one in this way will call the static constructor even if it was already executed, i.e., this code:

    Console.WriteLine(Statics1.Value1);
    
    Type staticType = typeof (Statics1);
    staticType.TypeInitializer.Invoke(null, null);
    

    will call the static constructor twice. So if your cctors have potentially important sideeffects, such as creating files, opening databases, etc, you might want to rethink this approach.

    Also, even though I prefer static constructors for reasons of readability, from a performance perspective, field initializers are a bit faster than static constructors