.Net: código en ejecución cuando se carga el ensamblado

¿Es posible ejecutar algún código cuando se carga un ensamblaje, sin hacer nada específico en el código de carga? Lo que estoy buscando es como un constructor estático en un tipo.

P.ej:

El ensamblaje A no sabe acerca del ensamblado B, pero B sí lo sabe sobre A. El ensamble A necesita saber ciertas cosas sobre B si B está cargado. Cuando el ensamblado B es cargado por el tiempo de ejecución (referenciado o explícito), quiero que se ejecute un fragmento de código (método o atributo estático) que llame a un método en el ensamblaje A.

La causa raíz de este problema son los tipos desconocidos que se encuentran al serializar un tipo en A que contiene tipos de B que no se conocen en el momento de la comstackción ya que se utilizan interfaces.

CLR admite inicializadores de módulo . Tendría que hackear el código de C ++ / CLI o ilasm.exe para usarlos.

(editar – se aplica a C #; para un enfoque de C ++, ver esta respuesta )

Básicamente, no: no puedes. Esta sería una gran superficie de ataque, y no está permitida. Es posible que desee colocar un controlador estático en algunos de los tipos B que garanticen la ejecución del código de inicio, pero eso es todo …

Puedes usar constructores estáticos en .Net, pero desafortunadamente no hacen lo que quieres. Los constructores estáticos solo se ejecutan justo antes de que se use un tipo. Consulte http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx para obtener más información.

Puede obtener un poco de millaje al suscribirse al evento AssemblyLoad de su AppDomain. Consulte http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx .

En su controlador de eventos, puede reflexionar sobre el ensamblaje recién cargado y hacer que ejecute el código que desee.

Hay 3 opciones para inicializar una Asamblea .NET:

  1. Usted escribe una función estática Init () o Main () en su Ensamblaje para inicializar y llama a esta función por reflexión desde el código C # que carga este Ensamblaje.
  2. Escriba un conjunto de C ++ administrado donde coloca su código en DllMain (). Tenga cuidado porque su código se ejecutará en el locking del cargador, donde están prohibidas varias cosas (como cargar otras DLL, …). Pero puede iniciar un nuevo hilo que CUALQUIER elemento de inicialización. (Acerca de LoaderLock: https://msdn.microsoft.com/en-us/library/ms173266.aspx ) (Acerca de DllMain: C # a C ++ / CLI a C DLL System.IO.FileNotFoundException )
  3. Comstack un ensamblado de C # puro y modifica la DLL comstackda para agregar un código de inicializador de módulo como se explica aquí: http://einaregilsson.com/module-initializers-in-csharp/ La desventaja de este método es que la función de inicialización no se llama inmediatamente cuando el ensamblaje se carga en el proceso. Pero se llama antes de acceder a cualquier otra cosa en el ensamblado.

Probablemente debería revisar su enfoque de serialización para mitigar este problema. Si serializa utilizando ISerializable y el atributo SerializableAttribute , puede hacer que el gráfico de serialización cargue el conjunto B cuando sea necesario sin que el conjunto A tenga que saber explícitamente sobre el conjunto B.

Utilizando un ensamblaje mixto puede hacer que DllMain se ejecute en una carga de ensamblaje.