Iniciales del módulo en C #

Los inicializadores de módulo son una característica del CLR que no están disponibles directamente en C # o VB.NET. Son métodos estáticos globales llamados .cctor que están garantizados para ejecutarse antes de que se ejecute cualquier otro código (inicializadores de tipo, constructores estáticos) en un ensamblado. Recientemente quise utilizar esto en un proyecto y pirateé mi propia solución (progtwig de consola / tarea msbuild) usando Mono.Cecil, pero me preguntaba:

  1. ¿Hay alguna forma de engañar al comstackdor de C # para que emita los inicializadores del módulo? ¿Algún atributo (por ejemplo, CompilerGenerated, SpecialName) u otro truco que se pueda usar?

  2. ¿Los C # / VB.NET alguna vez emiten estos inicializadores por algún motivo? Por lo que he visto, C ++ administrado los usa para algunos propósitos de interoperabilidad, pero no pude encontrar ninguna referencia a que se usen para otros fines. ¿Algunas ideas?

No, no hay forma de emitirlos en C #, porque C # pone todo en una clase / estructura y los inicializadores de módulos deben ser globales.

Deberá usar una herramienta diferente para escribirlos, preferiblemente IL-Assembler.

En cuanto a la segunda pregunta, tengo que admitir que no sé, pero nunca he visto ninguna generada por C #, y uso ILDasm con bastante frecuencia, así que supongo que no las emite.

Eche un vistazo al complemento de inicializador de módulo del impresionante proyecto opensource IL-Weaver ” fody “, escrito por Simone Cropp: https://github.com/fody/moduleinit

Le permite especificar un método que se traducirá en un inicializador de ensamblaje por fody:

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

obtiene esto:

 static () { ModuleInitializer.Initialize(); } 

Tal vez el System.Reflection.Emit nombres System.Reflection.Emit puede ayudarte. MethodAttributes enumeración MethodAttributes contiene elementos similares (SpecialName, RTSpecialName) .

Einar, tu pregunta no me dejó claro que ya escribiste una herramienta que permite inyectar un inicializador de módulo en un ensamblado ya comstackdo.

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

Intenté tu aplicación y funciona perfectamente. Mientras escribe, debería funcionar con todos los marcos actuales de 2 a 4.5.

Solo hay un problema que hace que su solución sea inútil para mí: se llama a su inicializador cuando la aplicación primero ACCEDE a cualquier cosa en el ensamblaje.

Lo que necesito es que se llame inmediatamente al inicializador del módulo cuando el ensamblado se carga en el proceso. Pero no lo es. Entonces, si la aplicación no accede al ensamblaje, nunca se inicializará.

Después de investigar todo un día, me parece que la única forma de conseguirlo es escribir un ensamblado de C ++ administrado y ejecutar el código en DllMain ().

Si tiene constructores estáticos o clases singleton a las que puede acceder con una variable estática, el comstackdor C # emitirá .cctor.