¿Cómo inicializar una clase estática en C # antes de que sea realmente necesaria?

Tengo una clase estática con un constructor estático que tarda algún tiempo (10-15 segundos) en ejecutarse e inicializar completamente la clase. Para mejorar el rendimiento, he decidido habilitar esta clase estática para que se inicialice explícitamente en lugar de cuando se necesita por primera vez para que esté lista para funcionar cuando realmente se necesita usar.

Mi primer pensamiento fue crear un método Initialize() para la clase, pero como ya tengo un constructor estático, este método no parece necesitar hacer nada más que ser el método al que se llama para inicializar explícitamente la clase sin acceder a ninguna clase. de sus otros métodos públicos o propiedades. Tener un método que no hace nada directamente no me parece correcto.

Luego pensé que solo podía mover el código del constructor estático a este método Initialize() , pero también me gustaría que la clase se inicializara cuando se necesita por primera vez y que no se haya llamado explícitamente al método Initialize() .

Para resumir, quiero que se cumplan los siguientes criterios:

  • Quiero permitir que la clase estática se inicialice explícitamente (probablemente utilizando un método de Initialize() público).
  • No quiero tener que acceder a ningún otro método público o propiedad en la clase cuando no los necesito, aunque esto inicialice la clase estática.
  • Si la clase no se ha inicializado explícitamente, todavía quiero inicializarla cuando se necesita por primera vez (es decir, cuando se accede a otros métodos o propiedades públicas con la intención de utilizar la funcionalidad o los datos que proporcionan).
  • Esta es una clase de ayuda y el uso del patrón de diseño Singleton no es necesario para mis propósitos.

¿Cuál sería la forma correcta de observar los criterios anteriores para una clase estática escrita en C #? Esto también puede aplicarse a otros lenguajes de progtwigción (por ejemplo, Java), pero personalmente estoy interesado en una solución escrita en C #.

Probablemente Initialize método de Initialize , y puede hacer algo útil:

  • Puede registrar que está intentando explícitamente inicializar la clase, con un seguimiento de stack
  • Podría lanzar una excepción si la clase ya está inicializada a través de otra llamada de Initialize
  • Posiblemente podría (con un poco de esfuerzo y reorganización) ordenar las cosas para que las excepciones causadas durante la inicialización se propagaran sin la TypeInitializationException que normalmente obtendría.

Me gustaría ir con el método de inicialización (EDIT: ver la respuesta de Jon). Pero si realmente solo quieres usar el constructor, puedes hacer esto:

 var type = typeof (YourType); System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle); 

RunClassConstructor permite forzar la ejecución del constructor de clase (constructor estático) si ya no lo ha hecho. Si ya se ha ejecutado, por ejemplo, porque usaste un miembro estático de la clase, esto no tiene efecto. Ejecutarlo veces adicionales no tiene efecto.

No estoy seguro de si puede especificar cuándo se carga un constructor estático.

Desde MSDN “Se llama automáticamente a un constructor estático para inicializar la clase antes de que se cree la primera instancia o se haga referencia a cualquier miembro estático”.

http://msdn.microsoft.com/en-us/library/k9x6w0hc(v=vs.80).aspx

* EDITAR: * ¿Le ayudaría agregar el patrón de singleton aquí? El captador puede llamar a Initialize () marcando una marca en la clase, IsLoaded = true. Las llamadas subsiguientes no llamarán Inicializar ()

Dos soluciones alternativas:

  1. Mueva el código del constructor a Initialize() para que pueda llamar explícitamente. Y reemplace el código dentro del constructor para simplemente llamar al método Initialize() en caso de que la clase estática se cargue dinámicamente antes de que lo haya llamado explícitamente

     public static class StaticClass { // actual constructor static StaticClass() { Initialize(); } // explicit "constructor" public static void Initialize() { MyProperty = "Some Value"; } public static string MyProperty { get; set; } } 

    Luego inicializa así si quieres:

     StaticClass.Initialize(); 

    O se inicializará dinámicamente la primera vez que se use

  2. No es tan prístino como semánticamente, pero puede desencadenar la inicialización orgánica de una clase estática simplemente consumiendo una propiedad y lanzándola en una variable temporal.

    Así que haz esto:

     // trigger static initilaization var dummy = StaticClass.MyProperty; 

    Todavía le permite llamarlo cuando lo necesite, pero si hay un costo de rendimiento en la inicialización, puede intentar invocarlo en el inicio, en lugar de la primera vez que el usuario hace algo que dispara ese código.

Para otro esquema útil de inicialización estática, vea: ¿Es el orden de inicialización de clase estática en C # determinista?

El enfoque no me parece mal. Podría nombrar el método Touch (), asignarle un cuerpo vacío y agregar un comentario apropiado. ¿Sería eso suficiente para superar tu sensación de que algo no se siente bien con esto?