c# - example - Equivalente a ''app.config'' para una biblioteca(DLL)
configurationmanager c# (12)
¿Hay un equivalente a app.config
para las bibliotecas (DLL)? De lo contrario, ¿cuál es la forma más fácil de almacenar las configuraciones que son específicas de una biblioteca? Tenga en cuenta que la biblioteca puede ser utilizada en diferentes aplicaciones.
Puede tener un archivo de configuración por separado, pero tendrá que leerlo "manualmente", ConfigurationManager.AppSettings["key"]
leerá solo la configuración del ensamblaje en ejecución.
Suponiendo que está utilizando Visual Studio como su IDE, puede hacer clic con el botón derecho en el proyecto deseado → Agregar → Nuevo elemento → Archivo de configuración de la aplicación
Esto agregará App.config
a la carpeta del proyecto, ponga su configuración allí en la sección <appSettings>
.
Ahora para leer de este archivo tiene esa función:
string GetAppSetting(Configuration config, string key)
{
KeyValueConfigurationElement element = config.AppSettings.Settings[key];
if (element != null)
{
string value = element.Value;
if (!string.IsNullOrEmpty(value))
return value;
}
return string.Empty;
}
Y para usarlo:
Configuration config = null;
string exeConfigPath = this.GetType().Assembly.Location;
try
{
config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
}
catch (Exception ex)
{
//handle errror here.. means DLL has no sattelite configuration file.
}
if (config != null)
{
string myValue = GetAppSetting(config, "myKey");
...
}
También deberá agregar una referencia al espacio de nombres System.Configuration para tener disponible la clase ConfigurationManager.
Al construir el proyecto, además de la DLL, también tendrá el archivo DllName.dll.config
, ese es el archivo que debe publicar con la DLL.
Lo anterior es un código de muestra básico, para aquellos interesados en un ejemplo a escala completa, por favor consulte esta otra respuesta .
public class ConfigMan
{
#region Memberes
string _assemblyLocation;
Configuration _configuration;
#endregion
#region Constructors
/// <summary>
/// Loads config file settings for libraries that use assembly.dll.config files
/// </summary>
/// <param name="assemblyLocation">The full path or UNC location of the loaded file that contains the manifest.</param>
public ConfigMan(string assemblyLocation)
{
_assemblyLocation = assemblyLocation;
}
#endregion
#region Properties
Configuration Configuration
{
get
{
if (_configuration == null)
{
try
{
_configuration = ConfigurationManager.OpenExeConfiguration(_assemblyLocation);
}
catch (Exception exception)
{
}
}
return _configuration;
}
}
#endregion
#region Methods
public string GetAppSetting(string key)
{
string result = string.Empty;
if (Configuration != null)
{
KeyValueConfigurationElement keyValueConfigurationElement = Configuration.AppSettings.Settings[key];
if (keyValueConfigurationElement != null)
{
string value = keyValueConfigurationElement.Value;
if (!string.IsNullOrEmpty(value)) result = value;
}
}
return result;
}
#endregion
}
Solo por algo que hacer refactoreé la respuesta principal en una clase. El uso es algo así como
ConfigMan configMan = new ConfigMan(this.GetType().Assembly.Location);
var setting = configMan.GetAppSetting("AppSettingsKey");
Los archivos de configuración tienen un ámbito de aplicación y no un ámbito de conjunto. Por lo tanto, deberá colocar las secciones de configuración de su biblioteca en el archivo de configuración de cada aplicación que esté utilizando su biblioteca.
Dicho esto, no es una buena práctica obtener la configuración del archivo de configuración de la aplicación, especialmente la sección appSettings
, en una biblioteca de clases. Si su biblioteca necesita parámetros, es probable que sean pasados como argumentos de método en constructores, métodos de fábrica, etc. por quien llame a su biblioteca. Esto evita que las aplicaciones que llaman reutilicen accidentalmente las entradas de configuración que esperaba la biblioteca de clases.
Dicho esto, los archivos de configuración XML son extremadamente útiles, por lo que el mejor compromiso que he encontrado es el uso de secciones de configuración personalizadas. Puedes poner la configuración de tu biblioteca en un archivo XML que el marco lee y analiza automáticamente y evitas posibles accidentes.
Puede obtener más información sobre las secciones de configuración personalizada en MSDN y también Phil Haack tiene un buen artículo sobre ellas.
Por lo que sé, debes copiar y pegar las secciones que deseas de la biblioteca .config en el archivo .config de las aplicaciones. Solo obtiene 1 app.config por instancia ejecutable.
Si agrega Configuración a un proyecto de Biblioteca de clases en Visual Studio (Propiedades del proyecto, Configuración), agregará un archivo app.config a su proyecto con las secciones userSettings / applicatioNSettings relevantes, y los valores predeterminados para estas configuraciones de Configuraciones. archivo.
Sin embargo, este archivo de configuración no se usará en tiempo de ejecución; en su lugar, la biblioteca de clases usa el archivo de configuración de su aplicación de alojamiento.
Creo que la razón principal para generar este archivo es para poder copiar / pegar la configuración en el archivo de configuración de la aplicación host.
los ensamblados no tienen su propio archivo app.config. Usan el archivo app.config de la aplicación que los está utilizando. Entonces, si su ensamblado espera ciertas cosas en el archivo de configuración, simplemente asegúrese de que el archivo de configuración de su aplicación tenga esas entradas allí.
Si su ensamblaje está siendo utilizado por múltiples aplicaciones, entonces cada una de esas aplicaciones deberá tener esas entradas en su archivo app.config.
Lo que recomendaría que haga es definir propiedades en las clases de su ensamblaje para esos valores, por ejemplo
private string ExternalServicesUrl
{
get
{
string externalServiceUrl = ConfigurationManager.AppSettings["ExternalServicesUrl"];
if (String.IsNullOrEmpty(externalServiceUrl))
throw new MissingConfigFileAppSettings("The Config file is missing the appSettings entry for: ExternalServicesUrl");
return externalServiceUrl;
}
}
Aquí, la propiedad ExternalServicesUrl obtiene su valor del archivo de configuración de la aplicación. Si alguna aplicación que usa este ensamblaje no tiene esa configuración en el archivo de configuración, obtendrá una excepción o está claro que algo se perdió.
MissingConfigFileAppSettings es una excepción personalizada. Es posible que desee lanzar una excepción diferente.
Por supuesto, un mejor diseño sería que el método de esas clases proporcione esos valores como parámetros en lugar de depender de la configuración del archivo de configuración. De esta forma, las aplicaciones que usan estas clases pueden decidir desde dónde y cómo proporcionan estos valores.
Use Agregar elemento existente, seleccione la configuración de la aplicación del proyecto dll. Antes de hacer clic en Agregar, use la pequeña flecha hacia abajo en el lado derecho del botón Agregar para "agregar como enlace"
Hago esto todo el tiempo en mi desarrollador.
En respuesta a la pregunta original, generalmente agrego el archivo de configuración en mi proyecto de prueba como un enlace; luego puede usar el atributo DeploymentItem para agregarlo a la carpeta Out de la ejecución de prueba.
[TestClass]
[DeploymentItem("MyProject.Cache.dll.config")]
public class CacheTest
{
.
.
.
.
}
En respuesta a los comentarios que las Asambleas no pueden ser específicas de un proyecto, pueden y proporcionan una gran flexibilidad, especialmente. cuando se trabaja con marcos IOC.
Actualmente estoy creando complementos para una marca de software minorista, que en realidad son bibliotecas de clase .net. Como requisito, cada complemento debe configurarse utilizando un archivo de configuración. Después de un poco de investigación y prueba, compilé la siguiente clase. Hace el trabajo sin problemas. Tenga en cuenta que no he implementado el manejo de excepciones locales en mi caso porque capturo excepciones en un nivel superior.
Es posible que sea necesario realizar algunos ajustes para obtener el punto decimal correcto, en el caso de los decimales y los dobles, pero funciona bien para mi CultureInfo ...
static class Settings
{
static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
static Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(uri.Path);
static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
static NumberFormatInfo nfi = new NumberFormatInfo()
{
NumberGroupSeparator = "",
CurrencyDecimalSeparator = "."
};
public static T Setting<T>(string name)
{
return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
}
Ejemplo de archivo App.Config
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:/" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
Uso:
somebooleanvar = Settings.Setting<bool>("Enabled");
somestringlvar = Settings.Setting<string>("ExportPath");
someintvar = Settings.Setting<int>("Seconds");
somedoublevar = Settings.Setting<double>("Ratio");
Créditos para Shadow Wizard & MattC
Enfrenté el mismo problema y lo resolví creando una clase estática Parámetros después de agregar un archivo de configuración de la aplicación al proyecto:
public static class Parameters
{
// For a Web Application
public static string PathConfig { get; private set; } =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "web.config");
// For a Class Library
public static string PathConfig { get; private set; } =
Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin", "LibraryName.dll.config");
public static string getParameter(string paramName)
{
string paramValue = string.Empty;
using (Stream stream = File.OpenRead(PathConfig))
{
XDocument xdoc = XDocument.Load(stream);
XElement element = xdoc.Element("configuration").Element("appSettings").Elements().First(a => a.Attribute("key").Value == paramName);
paramValue = element.Attribute("value").Value;
}
return paramValue;
}
}
A continuación, obtenga un parámetro como este:
Parameters.getParameter("keyName");
Desafortunadamente, solo puede tener un archivo app.config por ejecutable, por lo que si tiene DLL enlazados a su aplicación, no pueden tener sus propios archivos app.config.
La solución es: no es necesario que coloque el archivo App.config en el proyecto de la Biblioteca de clases.
Pone el archivo App.config en la aplicación que hace referencia al dll de la biblioteca de su clase.
Por ejemplo, supongamos que tenemos una biblioteca de clases llamada MyClasses.dll que utiliza el archivo app.config de la siguiente manera:
string connect =
ConfigurationSettings.AppSettings["MyClasses.ConnectionString"];
Ahora, digamos que tenemos una aplicación de Windows llamada MyApp.exe que hace referencia a MyClasses.dll. Contendrá un App.config con una entrada como:
<appSettings>
<add key="MyClasses.ConnectionString"
value="Connection string body goes here" />
</appSettings>
O
Un archivo xml es el mejor equivalente para app.config. Use xml serialize / deserialize según sea necesario. Puedes llamarlo como quieras. Si su configuración es "estática" y no necesita cambiar, también podría agregarla al proyecto como un recurso incrustado.
Espero que te dé una Idea
Preámbulo : estoy usando NET 2.0;
La solución publicada por Yiannis Leoussis es aceptable, pero tuve un problema con ella.
Primero, el static AppSettingsSection AppSettings = (AppSettingsSection)myDllConfig.GetSection("appSettings");
devuelve nulo. Tuve que cambiarlo a static AppSettingSection = myDllConfig.AppSettings;
A continuación, el return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
no tiene una trampa para Excepciones. Así que lo cambié
try
{
return (T)Convert.ChangeType(AppSettings.Settings[name].Value, typeof(T), nfi);
}
catch (Exception ex)
{
return default(T);
}
Esto funciona muy bien, pero si tiene una dll diferente, debe volver a escribir cada vez que se codifique cada ensamblaje. Por lo tanto, esta es mi versión para una clase para crear instancias cada vez que lo necesite.
public class Settings
{
private AppSettingsSection _appSettings;
private NumberFormatInfo _nfi;
public Settings(Assembly currentAssembly)
{
UriBuilder uri = new UriBuilder(currentAssembly.CodeBase);
string configPath = Uri.UnescapeDataString(uri.Path);
Configuration myDllConfig = ConfigurationManager.OpenExeConfiguration(configPath);
_appSettings = myDllConfig.AppSettings;
_nfi = new NumberFormatInfo()
{
NumberGroupSeparator = "",
CurrencyDecimalSeparator = "."
};
}
public T Setting<T>(string name)
{
try
{
return (T)Convert.ChangeType(_appSettings.Settings[name].Value, typeof(T), _nfi);
}
catch (Exception ex)
{
return default(T);
}
}
}
Para una configuración:
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:/" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
Úselo como:
Settings _setting = new Settings(Assembly.GetExecutingAssembly());
somebooleanvar = _settings.Setting<bool>("Enabled");
somestringlvar = _settings.Setting<string>("ExportPath");
someintvar = _settings.Setting<int>("Seconds");
somedoublevar = _settings.Setting<double>("Ratio");