Question

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.

Was it helpful?

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

OTHER TIPS

EDIT: explicitly won't work as-is, as poster states can't know the types in advance. Leaving here as might help clarification for future readers ...

If I understand your needs correctly -- in similar circumstances I create a wrapper that references the static class but remains part of the test suite. You can then instantiate the wrapper and have the static initialized on demand. It'd mean you can leave the architecture unchanged, and keep the wrapper as part of the test framework.

public static class MyStatic
{
    public static string SomeToolMethod()
    {
        return "Hello";
    }
}

public class MyStaticWrapper // or proxy, technically?
{
    public static string SomeToolMethod()
    {
        return MyStatic.SomeToolMethod();
    }
}

fooType.TypeInitializer.Invoke(new MyStaticWrapper()); /// untested, not sure of syntax here
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top