Question

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 souhaite ensuite accéder à Dir2 dans mon code en disant simplement:

 ConfigurationManager.AppSettings["Dir2"]

Cela m'aidera à installer mon application sur des serveurs et des emplacements différents pour lesquels je n'aurai qu'à changer UNE entrée dans mon intégralité <=>. (Je sais que je peux gérer toute la concaténation en code, mais je le préfère de cette façon).

Était-ce utile?

La solution

Bonne question.

Je ne pense pas qu'il y en ait. Je pense qu’il était assez bien connu s’il y avait un moyen simple et je vois que Microsoft crée un mécanisme dans Visual Studio 2010 pour le déploiement de 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 disposiez d'une sorte d'espace réservé appelé & Quot; | DataDirectory | & Quot ;. Peut-être pourriez-vous jeter un coup d’œil à ce qui se passe là-bas ...

Voici un extrait de machine.config l'affichage:

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

Autres conseils

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 app.config / web.config fichier, 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, 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"

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

Je pensais avoir vu 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, adaptez la configuration de l'application aux spécificités de l'environnement de déploiement cible. Quelques détails à ce sujet sur traiter avec la configuration-cauchemar

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 supportait 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.

Habituellement, je rédige une classe statique avec des propriétés permettant d'accéder à chacun des paramètres de mon fichier 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 également des conversions de type lorsque requis dans cette classe. Cela permet d’obtenir 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 simple et offre une facilité de maintenance bien supérieure.

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

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"]

Je vous suggérerais DslConfig . Avec DslConfig, vous pouvez utiliser les fichiers de configuration hiérarchiques de Global Config, Config par hôte serveur, pour configurer chaque application sur chaque hôte de serveur (voir AppSpike).
Si ceci est trop compliqué pour vous, vous pouvez simplement utiliser la configuration globale 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")

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.

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 en fonction de l'environnement.

<appSettings file="..\OverrideSettings.config">

Pour déployer des produits pour lesquels il est nécessaire de configurer de nombreux éléments avec des valeurs similaires, nous utilisons de petites applications console qui lisent le XML et se mettent à jour en fonction des paramètres entrés. Celles-ci sont ensuite appelées par le programme d'installation après utilisateur pour les informations requises.

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, recherchez LinIn dans la section DictionaryInfoConfigSection et renvoyez la valeur avec la clé correspondante. Cependant, vous devrez mettre à jour le fichier de configuration en créant quelque chose dans ce sens:

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

J'ai proposé cette solution:

  1. Dans l'application Settings.settings, j'ai défini une variable ConfigurationBase (avec type = chaîne 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, je lis la valeur si la ConfigurationBase
  4. Dans le fichier app.xaml.cs, j'ai remplacé toutes les variables par la valeur ConfigurationBase. Afin de 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, je dois le considérer dans le fichier app.xaml.cs.

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

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

MISE À JOUR

Je viens de trouver une amélioration (encore 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 de cette façon.

UPDATE2

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

Trois solutions possibles

  

Je sais que j'arrive en retard à la fête. Je cherchais de nouvelles solutions au problème des paramètres de configuration variables. Quelques réponses touchent les solutions que j'ai utilisées par le passé, mais la plupart semblent un peu compliquées. J'ai pensé examiner mes anciennes solutions et mettre en place les implémentations afin d'aider les personnes aux prises avec le même problème.

Pour cet exemple, j'ai utilisé le paramètre d'application suivant dans une application console:

<appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>

1. Utiliser les variables d'environnement

  

Je pense que l'autocro la réponse de l'auto a été abordé. Je fais juste une implémentation qui devrait suffire lors de la création ou du débogage sans avoir à fermer Visual Studio. J'ai utilisé cette solution dans la journée ...

  • Créer un événement de pré-génération qui utilisera les variables MSBuild

      

    Attention: utilisez une variable qui ne sera pas remplacée facilement, utilisez donc le nom de votre projet ou un nom similaire à celui de la variable.

    SETX BaseDir "$(ProjectDir)"

  • Réinitialiser les variables; en utilisant quelque chose comme ce qui suit:

    Actualiser les variables d'environnement en cas de dépassement de capacité de la pile

  • Utilisez le paramètre de votre code:

  • .

'

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. Utiliser une interpolation de chaîne:

  • Utilisez la fonction 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. En utilisant une classe statique, C’est la solution que j’utilise le plus souvent.

  • La mise en œuvre

`

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

`

  • La classe statique

`

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

`

Code du projet:

App.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
    </startup>
  <appSettings>
    <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/>
    <add key="StaticClassExample" value="bin"/>
    <add key="InterpollationExample" value="{0}bin"/>
  </appSettings>
</configuration>

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

Événement de pré-génération:

Paramètres du projet - > Créer des événements

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top