web-dev-qa-db-fra.com

Variables dans app.config/web.config

Est-il possible de faire quelque chose comme ce qui suit dans les fichiers app.config ou web.config?

<appSettings>
 <add key="MyBaseDir" value="C:\MyBase" />
 <add key="Dir1" value="[MyBaseDir]\Dir1"/>
 <add key="Dir2" value="[MyBaseDir]\Dir2"/>
</appSettings>

Je veux ensuite accéder à Dir2 dans mon code en disant simplement:

 ConfigurationManager.AppSettings["Dir2"]

Cela m'aidera lorsque j'installe mon application sur différents serveurs et emplacements où il me suffira de modifier UNE entrée dans l'ensemble de mon app.config..__ (je sais que je peux gérer toute la concaténation en code, mais je le préfère de cette façon). .

80
DeeStackOverflow

Bonne question.

Je ne pense pas qu'il y en ait. Je pense qu'il aurait été assez bien connu s'il existait un moyen simple et je vois que Microsoft crée un mécanisme dans Visual Studio 2010 pour déployer différents fichiers de configuration à des fins de déploiement et de test.

Cela dit, cependant; J'ai constaté que, dans la section ConnectionStrings, vous avez une sorte d'espace réservé appelé "| DataDirectory |". Peut-être pourriez-vous jeter un coup d'œil à ce qui se passe là-bas ...

Voici un morceau de machine.config le montrant:

 <connectionStrings>
    <add
        name="LocalSqlServer"
        connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
        providerName="System.Data.SqlClient"
    />
 </connectionStrings>
7
Arjan Einbu

Une alternative légèrement plus compliquée, mais beaucoup plus flexible, consiste à créer une classe qui représente une section de configuration. Dans votre fichier app.config/web.config, vous pouvez avoir ceci:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <!-- This section must be the first section within the <configuration> node -->
    <configSections>
        <section name="DirectoryInfo" type="MyProjectNamespace.DirectoryInfoConfigSection, MyProjectAssemblyName" />
    </configSections>

    <DirectoryInfo>
        <Directory MyBaseDir="C:\MyBase" Dir1="Dir1" Dir2="Dir2" />
    </DirectoryInfo>
</configuration>

Ensuite, dans votre code .NET (je vais utiliser C # dans mon exemple), vous pouvez créer deux classes comme celle-ci:

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);
            }
        }
    }
}

Enfin, dans votre code de programme, vous pouvez accéder à vos variables app.config, en utilisant vos nouvelles classes, de la manière suivante:

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

Vous pouvez utiliser ma bibliothèque Expansive: http://nuget.org/List/Packages/Expansive .__ La source est disponible ici: https://github.com/anderly/Expansive

14
anderly

Je pensais que je venais de voir cette question.

En bref, non, il n'y a pas d'interpolation de variable dans une configuration d'application. 

Vous avez deux options

  1. Vous pouvez lancer les vôtres pour substituer des variables au moment de l'exécution
  2. Au moment de la construction, modifiez la configuration de l'application avec les spécificités de l'environnement de déploiement cible. Quelques détails à ce sujet sur traitant de la configuration-cauchemar
4
Scott Weinstein

Vous avez plusieurs options. Vous pouvez le faire avec une étape de construction/déploiement qui traiterait votre fichier de configuration en remplaçant vos variables par la valeur correcte. 

Une autre option serait de définir votre propre section de configuration qui prend en charge cela. Par exemple, imaginez ce XML:

<variableAppSettings>
 <variables>
    <add key="@BaseDir" value="c:\Programs\Widget"/>
 </variables>
 <appSettings>
    <add key="PathToDir" value="@BaseDir\Dir1"/>
 </appSettings>
</variableAppSettings>

Maintenant, vous pouvez implémenter ceci en utilisant des objets de configuration personnalisés qui gèrent le remplacement des variables pour vous lors de l'exécution. 

3
JoshBerke

Habituellement, je finis par écrire une classe statique avec des propriétés pour accéder à chacun des paramètres de mon 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();
    }

}

Habituellement, je fais aussi des conversions de type lorsque cela est nécessaire dans cette classe. Cela permet d'avoir un accès dactylographié à votre configuration, et si les paramètres changent, vous pouvez les éditer à un seul endroit.

En règle générale, le remplacement des paramètres par cette classe est relativement facile et offre une facilité de maintenance bien supérieure.

3
Martin

Vous pouvez utiliser des variables d'environnement dans votre app.config pour le scénario que vous décrivez.

<configuration>
  <appSettings>
    <add key="Dir1" value="%MyBaseDir%\Dir1"/>
  </appSettings>
</configuration>

Ensuite, vous pouvez facilement obtenir le chemin avec:

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

Dans <appSettings>, vous pouvez créer des clés d’application,

<add key="KeyName" value="Keyvalue"/>

Plus tard, vous pourrez accéder à ces valeurs en utilisant: 

ConfigurationManager.AppSettings["Keyname"]
1
Sergio

Je vous suggérerais DslConfig . Avec DslConfig, vous pouvez utiliser les fichiers de configuration hiérarchiques de Global Config, Configuration par hôte hôte pour configurer chaque application sur chaque hôte serveur (voir AppSpike).
Si cela vous complique la tâche, vous pouvez simplement utiliser le fichier de configuration global Variables.var
Il suffit de configurer dans Varibales.var

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

Et obtenez les valeurs de configuration avec

Configuration config = new DslConfig.BooDslConfiguration()
config.GetVariable<string>("MyBaseDir")
config.GetVariable<string>("Dir1")
config.GetVariable<string>("Dir2")
1
Johannes

Je suis venu avec cette solution:

  1. Dans l'application Settings.settings, j'ai défini une variable ConfigurationBase (avec type = string Scope = Application)
  2. J'ai introduit une variable dans les attributs cibles dans les Settings.settings, tous ces attributs devaient être définis sur Scope = User
  3. Dans le fichier app.xaml.cs, j'ai lu la valeur si le ConfigurationBase
  4. Dans app.xaml.cs, j'ai remplacé toutes les variables par la valeur ConfigurationBase. Pour remplacer les valeurs au moment de l'exécution, les attributs devaient être définis sur Scopr = User.

Je ne suis pas vraiment satisfait de cette solution car je dois modifier tous les attributs manuellement. Si j'en ajoute un nouveau, je dois le considérer dans le fichier app.xaml.cs.

Voici un extrait de code du fichier App.xaml.cs:

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

METTRE &AGRAVE; JOUR

Je viens de trouver une amélioration (à nouveau un extrait de code provenant de app.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);
    }
}

Maintenant, les remplacements fonctionnent pour tous les attributs de mes paramètres ayant Type = chaîne et Scope = Utilisateur. Je pense que je l'aime comme ça.

UPDATE2

Apparemment, définir Scope = Application n'est pas requis pour exécuter les propriétés.

0
anhoppe

Je recommanderais de suivre la solution de Matt Hamsmith. S'il s'agit d'un problème à implémenter, pourquoi ne pas créer une méthode d'extension qui l'implémente en arrière-plan sur la classe AppSettings?

Quelque chose comme:

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

    }

Dans la méthode, vous effectuez une recherche dans DictionaryInfoConfigSection à l'aide de Linq et renvoyez la valeur avec la clé correspondante. Cependant, vous aurez besoin de mettre à jour le fichier de configuration en quelque chose du genre:

<appSettings>
  <DirectoryMappings>
    <DirectoryMap key="MyBaseDir" value="C:\MyBase" />
    <DirectoryMap key="Dir1" value="[MyBaseDir]\Dir1"/>
    <DirectoryMap key="Dir2" value="[MyBaseDir]\Dir2"/>
  </DirectoryMappings>
</appSettings>
0
Rich

Je ne pense pas que vous puissiez déclarer et utiliser des variables pour définir les clés appSettings dans un fichier de configuration. J'ai toujours géré les concaténations en code comme vous.

0

Je ne suis pas très à l'aise avec ce que vous voulez, mais vous pouvez ajouter un fichier de remplacement aux paramètres de l'application, puis définir ce fichier de remplacement selon l'environnement.

<appSettings file="..\OverrideSettings.config">
0
Andrew Barrett

Pour le déploiement de produits nécessitant la configuration de nombreux éléments avec des valeurs similaires, nous utilisons de petites applications console lisant le XML et les mettant à jour en fonction des paramètres entrés. Information requise.

0
cjk