2011-01-30 10 views
6

Tengo un ensamblado que contiene clases que importan varias clases de ensamblajes diferentes que no se referencian en tiempo de compilación pero que se descubren en tiempo de ejecución a través de un catálogo de directorio. Las clases de exportación desean definir secciones de configuración personalizadas para el archivo de configuración en la aplicación de host del ensamblaje de importación. Sin embargo, dado que la aplicación de host del ensamblaje de importación no conoce los ensamblados de exportación en tiempo de compilación, no puede cargar el ensamblado para usar las implementaciones de manejador de sección personalizadas en ellos.Secciones de configuración personalizadas en ensambles de exportación MEF

Una forma de solucionar este problema es colocar los ensamblados de exportación en la misma carpeta que el conjunto de la aplicación de host del conjunto de importación. Pero me gustaría permitir que otros desarrolladores configuren cualquier carpeta que quieran contener sus conjuntos de exportación.

Una cosa que puedo hacer es copiar el contenido de la carpeta configurada del desarrollador en la carpeta del host al inicio. Pero preferiría evitar esas partes y códigos móviles adicionales para mantener si puedo. ¿Hay una mejor manera de evitar esto? ¿Hay alguna manera de apuntar una aplicación a directorios adicionales cuando se buscan ensamblajes que definan secciones de configuración personalizadas?

+0

Si lograste encontrar una respuesta a tu problema, me encantaría leer sobre él ya que estoy enfrentando un problema que es muy similar. –

Respuesta

6

Me encontré con el mismo problema al usar StructureMap para descubrir ensamblajes dinámicamente. El ConfigurationManager parece buscar el Conjunto especificado para ConfigurationSection solo en Bin-Folder y GAC. No parece funcionar incluso si el ensamblado se cargó en el AppDomain actual.

Pero el hecho de que la Asamblea de la ConfigurationSection ya está cargado puede ser utilizado para una simple solución:

AppDomain.CurrentDomain.AssemblyResolve += (o, args) => 
     { 
      var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies(); 
      return loadedAssemblies.FirstOrDefault(asm => asm.FullName == args.Name); 
     }; 

El AssemblyResolve-El evento se activa cada vez que el CLR no puede encontrar un cierto Asamblea. Solo asegúrese de registrar la devolución de llamada antes de la primera llamada a GetSection().

Funciona para mí.

+1

Excelente solución Joachim, gracias! Tengo esto funcionando pero tuve un pequeño problema porque el ensamblado solicitado (args.Name) no tenía la versión y los componentes de cultivo en la cadena, pero sí el ensamblado cargado (asm.FullName). Entonces la cadena de fósforos no funcionó. A medida que avanzaba, otras asambleas solicitadas tenían la versión y la cultura, pero por alguna razón el particular en el que estoy interesado no lo hizo. Entonces, modifiqué la búsqueda a asm.FullName.Contains (args.Name).¿Alguna idea de por qué la versión y la cultura no serían parte de la solicitud de un ensamblaje, pero es para otros? –

+0

¡Gracias, esto tiene sentido! PD. simplemente puede escribir 'loadedAssemblies.FirstOrDefault (a => a.FullName == args.Name);' en lugar de usar el 'Dónde' adicional. ; p –

+0

¡Cambió eso! Gracias. –

0

Por lo que yo sé, las secciones de configuración solo se leen cuando se accede a ellas a través del GetSection(). Si su código de módulo es lo único que llama al ConfigurationManager.GetSection("myModuleConfigSection"), entonces probablemente no importará, ya que en este punto el ensamblaje se ha cargado en el AppDomain. Si esa sección se lee antes de que su ensamblaje se cargue en el AppDomain, entonces me imagino que obtendría una excepción.

Probablemente pueda agregar su ruta de módulo a la ruta de contenedor privado que el AppDomain utiliza para la resolución de conjunto. Al agregar una ruta adicional, permite que se resuelvan los ensamblados que no están actualmente cargados.

+0

Matthew - gracias. El módulo con el manejador de sección realiza la llamada después de que la composición MEF la crea, así que supongo que está cargada en el dominio de aplicación en ese momento (esta es la razón por la que me sorprendió que el tipo de manejador no se pudiera resolver). Una cosa que es diferente es que no estoy llamando a ConfigurationManager.GetSection como describes. En cambio, obtengo una Configuración de ConfigurationManager.OpenExeConfiguration y llamo a Configuration.GetSection. No estoy seguro de si eso tendría algún efecto, pero probaré el enfoque ConfigurationManager.GetSection y lo veré. –

Cuestiones relacionadas