Variables dentro de app.config / web.config

¿Es posible hacer algo como lo siguiente en los archivos app.config o web.config ?

      

Luego quiero acceder a Dir2 en mi código simplemente diciendo:

  ConfigurationManager.AppSettings["Dir2"] 

Esto me ayudará cuando instale mi aplicación en diferentes servidores y ubicaciones, donde solo tendré que cambiar UNA entrada en toda mi app.config . (Sé que puedo administrar toda la concatenación en el código, pero lo prefiero de esta manera).

Buena pregunta.

No creo que exista. Creo que habría sido bastante conocido si hubiera una manera fácil, y veo que Microsoft está creando un mecanismo en Visual Studio 2010 para implementar diferentes archivos de configuración para implementación y prueba.

Dicho eso, sin embargo; He encontrado que en la sección ConnectionStrings tiene un tipo de marcador de posición llamado “| DataDirectory |”. Tal vez puedas echar un vistazo a lo que está trabajando allí …

Aquí hay una pieza de machine.config que lo muestra:

     

Una alternativa un poco más complicada, pero mucho más flexible, es crear una clase que represente una sección de configuración. En su archivo app.config / web.config , puede tener esto:

     

Luego, en su código .NET (usaré C # en mi ejemplo), puede crear dos clases como esta:

 using System; using System.Configuration; namespace MyProjectNamespace { public class DirectoryInfoConfigSection : ConfigurationSection { [ConfigurationProperty("Directory")] public DirectoryConfigElement Directory { get { return (DirectoryConfigElement)base["Directory"]; } } public class DirectoryConfigElement : ConfigurationElement { [ConfigurationProperty("MyBaseDir")] public String BaseDirectory { get { return (String)base["MyBaseDir"]; } } [ConfigurationProperty("Dir1")] public String Directory1 { get { return (String)base["Dir1"]; } } [ConfigurationProperty("Dir2")] public String Directory2 { get { return (String)base["Dir2"]; } } // You can make custom properties to combine your directory names. public String Directory1Resolved { get { return System.IO.Path.Combine(BaseDirectory, Directory1); } } } } 

Finalmente, en su código de progtwig, puede acceder a sus variables app.config , usando sus nuevas clases, de esta manera:

 DirectoryInfoConfigSection config = (DirectoryInfoConfigSection)ConfigurationManager.GetSection("DirectoryInfo"); String dir1Path = config.Directory.Directory1Resolved; // This value will equal "C:\MyBase\Dir1" 

Puede lograr el uso de mi biblioteca expansiva: http://nuget.org/List/Packages/Expansive Source está disponible aquí: https://github.com/anderly/Expansive

Pensé que acabo de ver esta pregunta.

En resumen, no, no hay interpolación variable dentro de una configuración de aplicación.

Tienes dos opciones

  1. Podrías rodar tu propio para sustituir variables en tiempo de ejecución
  2. En tiempo de comstackción, aplique un masaje a la configuración de la aplicación según los detalles específicos del entorno de despliegue del objective. Algunos detalles sobre esto al tratar con la configuración-pesadilla

Tienes unas cuantas opciones. Puede hacer esto con un paso de comstackción / implementación que procese su archivo de configuración reemplazando sus variables con el valor correcto.

Otra opción sería definir su propia sección de Configuración que sea compatible con esto. Por ejemplo, imagine este xml:

         

Ahora implementaría esto usando objetos de configuración personalizados que manejarían reemplazar las variables en tiempo de ejecución.

Usualmente, termino escribiendo una clase estática con propiedades para acceder a cada una de las configuraciones de mi web.config.

 public static class ConfigManager { public static string MyBaseDir { return ConfigurationManager.AppSettings["MyBaseDir"].toString(); } public static string Dir1 { return MyBaseDir + ConfigurationManager.AppSettings["Dir1"].toString(); } } 

Por lo general, también escribo conversiones cuando es necesario en esta clase. Permite tener un acceso escrito a su configuración, y si la configuración cambia, puede editarlos en un solo lugar.

Por lo general, reemplazar las configuraciones con esta clase es relativamente fácil y proporciona una capacidad de mantenimiento mucho mayor.

Yo sugeriría que DslConfig . Con DslConfig puede usar archivos de configuración jerárquica desde Configuración global, Configuración por host de servidor a configuración por aplicación en cada host de servidor (consulte la aplicación AppSpike).
Si esto es complicado para usted, puede usar la configuración global Variables.var
Simplemente configure en Varibales.var

 baseDir = "C:\MyBase" Var["MyBaseDir"] = baseDir Var["Dir1"] = baseDir + "\Dir1" Var["Dir2"] = baseDir + "\Dir2" 

Y obtenga los valores de configuración con

 Configuration config = new DslConfig.BooDslConfiguration() config.GetVariable("MyBaseDir") config.GetVariable("Dir1") config.GetVariable("Dir2") 

Puedes usar variables de entorno en tu app.config para ese escenario que describes

      

Entonces puedes obtener fácilmente el camino con:

 var pathFromConfig = ConfigurationManager.AppSettings["Dir1"]; var expandedPath = Environment.ExpandEnvironmentVariables(pathFromConfig); 

No creo que pueda declarar y usar variables para definir las claves AppSettings dentro de un archivo de configuración. Siempre he manejado concatenaciones en código como tú.

Estoy luchando un poco con lo que quieres, pero puedes agregar un archivo de anulación a la configuración de la aplicación y luego tener ese archivo de anulación por cada entorno.

  

Para implementar productos en los que necesitamos configurar muchos elementos con valores similares, usamos aplicaciones de consola pequeñas que leen el XML y las actualizan en función de los parámetros que se ingresan. Luego el instalador las llama y luego de solicitarle al usuario el información requerida.

Yo recomendaría seguir la solución de Matt Hamsmith. Si se trata de un problema para implementar, ¿por qué no crear un método de extensión que implemente esto en segundo plano en la clase AppSettings?

Algo como:

  public static string GetValue(this NameValueCollection settings, string key) { } 

Dentro del método, busca a través de DictionaryInfoConfigSection usando Linq y devuelve el valor con la clave correspondiente. Sin embargo, necesitará actualizar el archivo de configuración, a algo similar a lo siguiente:

        

Dentro de puede crear claves de aplicación,

  

Más adelante puede acceder a estos valores usando:

 ConfigurationManager.AppSettings["Keyname"] 

Se me ocurrió esta solución:

  1. En la aplicación Settings.settings, definí una variable ConfigurationBase (con type = string Scope = Application)
  2. Introduje una variable en los atributos de destino en Settings.settings, todos esos atributos tenían que establecerse en Scope = User
  3. En la aplicación.xaml.cs leí el valor si el ConfigurationBase
  4. En la aplicación.xaml.cs reemplacé todas las variables con el valor de ConfigurationBase. Para reemplazar los valores en tiempo de ejecución, los atributos deben establecerse en Scopr = Usuario

No estoy muy contento con esta solución porque tengo que cambiar todos los atributos de forma manual, si agrego uno nuevo, tengo que considerarlo en la aplicación.xaml.cs.

Aquí un fragmento de código de la aplicación.xaml.cs:

 string configBase = Settings.Default.ConfigurationBase; Settings.Default.CommonOutput_Directory = Settings.Default.CommonOutput_Directory.Replace("${ConfigurationBase}", configBase); 

ACTUALIZAR

Acabo de encontrar una mejora (de nuevo un fragmento de código de la aplicación.xaml.cs):

 string configBase = Settings.Default.ConfigurationBase; foreach (SettingsProperty settingsProperty in Settings.Default.Properties) { if (!settingsProperty.IsReadOnly && settings.Default[settingsProperty.Name] is string) { Settings.Default[settingsProperty.Name] = ((string)Settings.Default[settingsProperty.Name]).Replace("${ConfigurationBase}", configBase); } } 

Ahora los reemplazos funcionan para todos los atributos en mi configuración que tienen Type = string y Scope = User. Creo que me gusta de esta manera.

ACTUALIZACIÓN2

Aparentemente establecer Ámbito = La aplicación no es necesaria cuando se ejecuta sobre las propiedades.

Tres posibles soluciones

Sé que llegaré tarde a la fiesta, he estado buscando si había nuevas soluciones para el problema de las configuraciones de configuración variable. Hay algunas respuestas que tocan las soluciones que he usado en el pasado, pero la mayoría parecen un poco intrincadas. Pensé en ver mis soluciones anteriores y poner las implementaciones juntas para que puedan ayudar a las personas que están luchando con el mismo problema.

Para este ejemplo, he utilizado la siguiente configuración de la aplicación en una aplicación de consola:

      

1. Usar variables de entorno

Creo que la respuesta del autocro autocroc lo tocó. Solo estoy haciendo una implementación que debería ser suficiente para construir o depurar sin tener que cerrar Visual Studio. He usado esta solución en el día …

  • Crear un evento de preconstrucción que usará las variables MSBuild

    Advertencia: use una variable que no será reemplazada fácilmente, entonces use el nombre de su proyecto o algo similar como un nombre de variable.

    SETX BaseDir "$(ProjectDir)"

  • Restablecer variables; usando algo como lo siguiente:

    Actualizar variables de entorno en desbordamiento de stack

  • Usa la configuración en tu código:

 private void Test_Environment_Variables() { string BaseDir = ConfigurationManager.AppSettings["EnvironmentVariableExample"]; string ExpandedPath = Environment.ExpandEnvironmentVariables(BaseDir).Replace("\"", ""); //The function addes a " at the end of the variable Console.WriteLine($"From within the C# Console Application {ExpandedPath}"); } 

2. Utilice la interpolación de cadenas:

  • Use la función string.Format ()

`

 private void Test_Interpollation() { string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"]; string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\")); string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString()); Console.WriteLine($"Using old interpollation {ExpandedPath}"); } 

`

3. Usando una clase estática, esta es la solución que uso principalmente.

  • La implementación

`

 private void Test_Static_Class() { Console.WriteLine($"Using a static config class {Configuration.BinPath}"); } 

`

  • La clase estática

`

 static class Configuration { public static string BinPath { get { string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"]; string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\")); return SolutionPath + ConfigPath; } } } 

`

Código de proyecto:

App.config:

            

Program.cs

 using System; using System.Configuration; using System.IO; namespace ConfigInterpollation { class Program { static void Main(string[] args) { new Console_Tests().Run_Tests(); Console.WriteLine("Press enter to exit"); Console.ReadLine(); } } internal class Console_Tests { public void Run_Tests() { Test_Environment_Variables(); Test_Interpollation(); Test_Static_Class(); } private void Test_Environment_Variables() { string ConfigPath = ConfigurationManager.AppSettings["EnvironmentVariableExample"]; string ExpandedPath = Environment.ExpandEnvironmentVariables(ConfigPath).Replace("\"", ""); Console.WriteLine($"Using environment variables {ExpandedPath}"); } private void Test_Interpollation() { string ConfigPath = ConfigurationManager.AppSettings["InterpollationExample"]; string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\")); string ExpandedPath = string.Format(ConfigPath, SolutionPath.ToString()); Console.WriteLine($"Using interpollation {ExpandedPath}"); } private void Test_Static_Class() { Console.WriteLine($"Using a static config class {Configuration.BinPath}"); } } static class Configuration { public static string BinPath { get { string ConfigPath = ConfigurationManager.AppSettings["StaticClassExample"]; string SolutionPath = Path.GetFullPath(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"..\..\")); return SolutionPath + ConfigPath; } } } } 

Evento de preconstrucción:

Configuración del proyecto -> Eventos de comstackción