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

Possible duplicate:
How to call a static constructor with reflection?

I have initialization code in the static constructor of various classes. I cannot create instances and do not know types in advance. I would like to provide loading classes.

I tried this:

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

But got a MemberAccessException: The type initializer was not called.

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

Edit: I found a workaround using the RuntimeHelpers.RunClassConstructor , but this method seems to be almost undocumented on MSDN, and I'm not sure if it is a hacked or sensible, prod system, as a way.

+7
source share
2 answers

I'm not sure why this works, but as far as I know (using 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 an exception, because somehow it solves for the .ctor, and not for the .cctor class.
If I use an explicitly static class, it is considered as an abstract closed class, so the exception is that the abstract class cannot be created, and if I use a regular class with a static constructor, the exception is that the type initializer is not called back.

But if I use Invoke overload with two parameters (instance, params), for example:

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

explicitly indicating that I am invoking a static method (that the value of the first null is no instance == static), this works and initializes the class.


However, static constructors are strange beasts. Calling one in this way will invoke the static constructor, even if it is already executed , that is, this code:

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

will invoke the static constructor twice. Therefore, if your clicks have potentially important side effects, such as creating files, opening databases, etc., you can reconsider this approach.

Also, although I prefer static constructors for readability, in terms of performance, field initializers are slightly faster than static constructors

+8
source

EDIT: Explicitly will not work as it is, since poster states cannot know the types in advance. Leaving here how can help clarify to future readers ...

If I understand your needs correctly, in such circumstances, I create a wrapper that references a static class, but remains part of the test suite. You can then instantiate the shell and statically initialize on demand. This means that you can leave the architecture unchanged and keep the shell as part of the test environment.

  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
0
source

All Articles