c# - studio - Sección de configuración personalizada: No se pudo cargar el archivo o el ensamblaje
config file c# (7)
¿Podría verificar que las rutas de sondeo están configuradas correctamente en el archivo de configuración de su aplicación Host? Es posible que una referencia necesaria no se esté cargando en su dominio de aplicación actual.
Me está costando mucho intentar acceder a una sección de configuración personalizada en mi archivo de configuración.
El archivo de configuración se está leyendo desde un archivo .dll que se carga como un complemento. Creé la configuración y el código necesario utilizando el complemento de la Sección de configuración Diseñador VS.
El espacio de nombres es ''ImportConfiguration''. La clase ConfigurationSection es ''ImportWorkflows''. El ensamblaje es ImportEPDMAddin.
El xml:
<configSections>
<section name="importWorkflows" type="ImportConfiguration.ImportWorkflows, ImportEPDMAddin"/>
</configSections>
Cada vez que intento leer en la configuración, me sale el error:
Se produjo un error al crear el controlador de la sección de configuración para importWorkflows: no se pudo cargar el archivo o el ensamblaje ''ImportEPDMAddin.dll'' o una de sus dependencias. El sistema no puede encontrar el archivo especificado.
La dll no residirá en el mismo directorio que el ejecutable, ya que el software que carga el complemento coloca la dll y sus dependencias en su propio directorio. (No puedo controlar eso)
Edité el código para la instancia de singleton a lo siguiente:
string path = System.Reflection.Assembly.GetCallingAssembly().CodeBase;
path = path.Replace("file:///", "");
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(path);
return configuration.GetSection(ImportWorkflowsSectionName) as ImportConfiguration.ImportWorkflows;
También he intentado usar un NameValueFileSectionHandler simple, pero tengo una excepción que dice que no se puede cargar el archivo o el ensamblaje ''Sistema''.
He leído numerosas publicaciones y artículos de blogs y parece que es posible leer un archivo de configuración para una DLL, pero simplemente no puedo hacer que funcione. ¿Algunas ideas? Gracias.
¿Te has asegurado de que la DLL se carga primero? Tal vez con Assembly.LoadFile("PATH")
?
Si no puede hacer que las clases en System.Configuration funcionen correctamente, siempre puede recurrir al uso de XmlDocument para analizar manualmente el archivo de configuración. Utilice XPaths para facilitar la obtención de datos. Por ejemplo (asumiendo su variable de ruta arriba):
var document = new XmlDocument();
document.Load(path);
var node = document.SelectSingleNode("configuration/importWorkflows/add[@name=''KEY'']");
// Do whatever with node
Desafortunadamente, deberá tener el ensamblaje ImportEPDMAddin
que reside en la misma carpeta que su archivo ejecutable, que reside en la carpeta del marco .Net relacionada con el marco .Net que está utilizando (es decir, C: / Windows / Microsoft.NET / Framework / v2.0.50727), o registrado en la memoria caché de ensamblados global.
La única otra opción es, si conoce la ruta al ensamblaje que contiene la clase de definición del manejador de configuración, puede cargarla sin una referencia con algo como esto:
//Class global
private Assembly configurationDefiningAssembly;
protected TConfig GetCustomConfig<TConfig>(string configDefiningAssemblyPath,
string configFilePath, string sectionName) where TConfig : ConfigurationSection
{
AppDomain.CurrentDomain.AssemblyResolve += new
ResolveEventHandler(ConfigResolveEventHandler);
configurationDefiningAssembly = Assembly.LoadFrom(configDefiningAssemblyPath);
var exeFileMap = new ExeConfigurationFileMap();
exeFileMap.ExeConfigFilename = configFilePath;
var customConfig = ConfigurationManager.OpenMappedExeConfiguration(exeFileMap,
ConfigurationUserLevel.None);
var returnConfig = customConfig.GetSection(sectionName) as TConfig;
AppDomain.CurrentDomain.AssemblyResolve -= ConfigResolveEventHandler;
return returnConfig;
}
protected Assembly ConfigResolveEventHandler(object sender, ResolveEventArgs args)
{
return configurationDefiningAssembly;
}
Asegúrese de manejar el evento AssemblyResolve, ya que esto generará una excepción sin él.
En su archivo de configuración de aplicaciones principales, agregue lo siguiente (donde los complementos son la carpeta desde donde se carga su ensamblaje. Puede usar varias rutas separadas por punto y coma.
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath=".;./Plugins"/>
</assemblyBinding>
</runtime>
Tomado de http://msdn.microsoft.com/en-us/library/823z9h8w%28v=vs.90%29.aspx
Intenté la respuesta de AJ, con el suplemento de rileywhite, pero descubrí que no me funcionó.
En mi escenario, la clase de ConfigurationSection personalizada ya estaba en el ensamblaje que se está ejecutando actualmente, y al intentar cargarla se produce un desbordamiento de pila. Tampoco quise incluirlo en GAC, aunque resolvió el problema según lo informado por el OP.
Al final, encontré que esto funciona lo suficientemente bien para mi propósito. Quizás a otros les resulte útil:
public class CustomConfigurationSection : ConfigurationSection {
public CustomConfigurationSection()
{
var reader = XmlReader.Create(<path to my dll.config>);
reader.ReadToDescendant("CustomConfigurationSection");
base.DeserializeElement(reader,false);
}
// <rest of code>
}
Para ampliar la excelente respuesta de AJ, aquí hay una clase personalizada para ayudar con la sobrecarga de registrar y eliminar el evento global.
public sealed class AddinCustomConfigResolveHelper : IDisposable
{
public AddinCustomConfigResolveHelper(
Assembly addinAssemblyContainingConfigSectionDefinition)
{
Contract.Assert(addinAssemblyContainingConfigSectionDefinition != null);
this.AddinAssemblyContainingConfigSectionDefinition =
addinAssemblyContainingConfigSectionDefinition;
AppDomain.CurrentDomain.AssemblyResolve +=
this.ConfigResolveEventHandler;
}
~AddinCustomConfigResolveHelper()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool isDisposing)
{
AppDomain.CurrentDomain.AssemblyResolve -= this.ConfigResolveEventHandler;
}
private Assembly AddinAssemblyContainingConfigSectionDefinition { get; set; }
private Assembly ConfigResolveEventHandler(object sender, ResolveEventArgs args)
{
// often the name provided is partial...this will match full or partial naming
if (this.AddinAssemblyContainingConfigSectionDefinition.FullName.Contains(args.Name))
{
return this.AddinAssemblyContainingConfigSectionDefinition;
}
return null;
}
}
Sugeriría crear una instancia en una declaración usando, así:
// you''ll need to populate these two variables
var configuration = GetConfiguration();
var assembly = GetAssemblyContainingConfig();
using(new AddinCustomConfigResolveHelper(assembly))
{
return (MyConfigSection)configuration.GetSection("myConfigSection");
}
Tuvo que usar la cadena de tipo completamente calificada de mi módulo / conjunto de plugin, que está en un directorio de sondeo, para poder ubicarlo. Usando EntityFramework como ejemplo ...
Incorrecto:
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework"
Correcto
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"