Inicializar la biblioteca en la carga de ensamblaje

Tengo un dll de biblioteca .net que actúa como una biblioteca funcional. Hay un montón de tipos estáticos junto con métodos estáticos.

Hay un código de inicialización que necesito ejecutar para configurar la biblioteca lista para usar.

Cuando se carga el ensamblaje, ¿hay alguna manera de garantizar que se ejecute un método en particular? Algo así como AppDomain.AssemblyLoad, pero se llama automáticamente desde el propio ensamblado. Estaba pensando que tal vez hay algo así como un AssemblyAttribute que podría ser utilizado?

Por el momento tengo este código de inicialización en un constructor estático, pero como se trata de una biblioteca con muchos puntos de entrada, no hay garantía de que se use este tipo particular.

¡Gracias!

¿Por qué necesita que se carguen todos los datos antes de usarlos, y no solo cuando se utiliza el primer tipo que los necesita?

No creo que haya ninguna forma de obligar a un método a ejecutarse en la carga de ensamblaje, desde dentro del ensamblaje. Podría poner un constructor estático en cada tipo, pero francamente creo que tiene más sentido tener un solo tipo que represente esos datos y proporcionar acceso a él, y poner un constructor estático solo en ese tipo. (Si tiene partes de datos separadas que se pueden usar de forma independiente, quizás cree tipos separados para ellas).

Sí, hay, más o menos.

Usa la excelente pequeña utilidad de Einar Egilsson, InjectModuleInitializer .

Ejecute este ejecutable como un paso posterior a la comstackción para crear una pequeña función .cctor (la función de inicialización del módulo) que invoca una función estática de vacío que no toma parámetros. Sería bueno si el comstackdor nos dio la capacidad de crear .cctor (), afortunadamente rara vez necesitamos esta capacidad.

Sin embargo, este no es un reemplazo completo de DllMain. El CLR solo llama a esta función .cctor antes de cualquier método llamado en su ensamblaje, no en la carga de ensamblaje. Por lo tanto, si necesita que suceda algo al momento de la carga del ensamblaje, debe hacer que el código de carga llame directamente a un método o utilice el truco que detallo en https://stackoverflow.com/a/9745422/240845.

La siguiente solución solo es posible cuando se tiene control sobre el conjunto principal de ejecución, es decir, no es adecuado para bibliotecas independientes destinadas a la distribución.

Tuve un problema similar y lo resolví creando un atributo dirigido a ensamblados ‘InitializeOnLoad’ con un parámetro Type. Luego, en el archivo ejecutable principal, agregué un controlador trivial AppDomain.AssemblyLoaded, que escanea el ensamblaje recién cargado para el atributo antes mencionado y llama a System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor () en ellos.

 [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] public class InitializeOnLoadAttribute : Attribute { Type type; public InitializeOnLoadAttribute(Type type) { this.type = type; } public Type Type { get { return type; } } } // somewhere very early in main exe initialization AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(AssemblyInitializer); static void AssemblyInitializer(object sender, AssemblyLoadEventArgs args) { // force static constructors in types specified by InitializeOnLoad foreach (InitializeOnLoadAttribute attr in args.LoadedAssembly.GetCustomAttributes(typeof(InitializeOnLoadAttribute), false)) System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(attr.Type.TypeHandle); } 

Además, si tiene miedo de que los ensamblajes se hayan cargado antes de enganchar el evento AssemblyLoad, simplemente puede ejecutar AppDomain.GetAssemblies () y llamar al ‘inicializador’ para ellos.

Es posible: simplemente agrega un constructor estático a la clase . Sin embargo, no sé cómo lograr esto sin una modificación IL.