wake-up-neo.net

Variablen in app.config/web.config

Ist es möglich, etwas in den app.config- oder web.config-Dateien zu tun?

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

Ich möchte dann in meinem Code auf Dir2 zugreifen, indem ich einfach sagt:

 ConfigurationManager.AppSettings["Dir2"]

Dies hilft mir, wenn ich meine Anwendung auf verschiedenen Servern und Orten installiere, an denen ich nur EINEN Eintrag in meinem gesamten app.config..__ ändern muss. .

80

Gute Frage.

Ich glaube nicht, dass es so ist. Ich glaube, es wäre ziemlich bekannt gewesen, wenn es einen einfachen Weg gegeben hätte, und ich sehe, dass Microsoft in Visual Studio 2010 einen Mechanismus zum Bereitstellen verschiedener Konfigurationsdateien für die Bereitstellung und den Test erstellt.

Mit diesem gesagt jedoch; Ich habe festgestellt, dass Sie im Abschnitt ConnectionStrings eine Art Platzhalter namens "| DataDirectory |" haben. Vielleicht kannst du dir mal ansehen, was dort am Werk ist ...

Hier ist ein Stück von machine.config, das es zeigt:

 <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

Eine etwas kompliziertere, aber weitaus flexiblere Alternative ist das Erstellen einer Klasse, die einen Konfigurationsabschnitt darstellt. In Ihrer app.config/web.config-Datei können Sie Folgendes haben:

<?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>

Dann können Sie in Ihrem .NET-Code (ich verwende C # in meinem Beispiel) zwei Klassen wie folgt erstellen:

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

Schließlich können Sie in Ihrem Programmcode auf Ihre app.config-Variablen mit Ihren neuen Klassen auf folgende Weise zugreifen:

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

Sie können dies mit meiner Expansive-Bibliothek tun: http://nuget.org/List/Packages/Expansive Die Quelle ist hier verfügbar: https://github.com/anderly/Expansive

14
anderly

Ich dachte, ich hätte diese Frage gerade gesehen.

Kurz gesagt, nein, es gibt keine variable Interpolation innerhalb einer Anwendungskonfiguration. 

Sie haben zwei Möglichkeiten

  1. Sie können Ihre eigene Rolle rollen, um Variablen zur Laufzeit zu ersetzen
  2. Zum Erstellungszeitpunkt können Sie die Anwendungskonfiguration an die Besonderheiten der Zielbereitstellungsumgebung anpassen. Einige Details dazu unter Umgang mit dem Konfigurations-Alptraum
4
Scott Weinstein

Sie haben mehrere Möglichkeiten. Sie können dies mit einem Erstellungs-/Bereitstellungsschritt tun, der Ihre Konfigurationsdatei verarbeitet und Ihre Variablen durch den richtigen Wert ersetzt. 

Eine andere Option wäre, einen eigenen Konfigurationsabschnitt zu definieren, der dies unterstützt. Stellen Sie sich zum Beispiel dieses XML vor:

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

Nun würden Sie dies mit benutzerdefinierten Konfigurationsobjekten implementieren, die die Ersetzung der Variablen zur Laufzeit für Sie erledigen würden. 

3
JoshBerke

Normalerweise schreibe ich eine statische Klasse mit Eigenschaften, um auf alle Einstellungen meiner web.config zuzugreifen.

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

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

}

Normalerweise tippe ich auch Konvertierungen ein, wenn dies in dieser Klasse erforderlich ist. Sie haben einen typisierten Zugriff auf Ihre Konfiguration. Wenn sich die Einstellungen ändern, können Sie sie nur an einer Stelle bearbeiten.

Normalerweise ist das Ersetzen von Einstellungen durch diese Klasse relativ einfach und bietet eine viel größere Wartbarkeit.

3
Martin

Sie können Umgebungsvariablen in Ihrem app.config für das von Ihnen beschriebene Szenario verwenden

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

Dann können Sie den Weg leicht mit folgendem ermitteln:

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

In <appSettings> können Sie Anwendungsschlüssel erstellen.

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

Später können Sie auf diese Werte zugreifen mit: 

ConfigurationManager.AppSettings["Keyname"]
1
Sergio

Ich würde vorschlagen, Sie DslConfig . Mit DslConfig können Sie hierarchische Konfigurationsdateien aus Global Config, Config pro Serverhost zur Konfiguration pro Anwendung auf jedem Serverhost verwenden (siehe AppSpike).
Wenn dies für Sie zu kompliziert ist, können Sie einfach die globale Konfigurationsvariable.var verwenden
Konfigurieren Sie einfach in Varibales.var

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

Und bekomme die Konfigurationswerte mit

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

Ich habe diese Lösung gefunden:

  1. In der Anwendung Settings.settings habe ich eine Variable ConfigurationBase definiert (mit type = string Scope = Application)
  2. Ich habe eine Variable in die Zielattribute in den Settings.settings eingefügt. All diese Attribute mussten auf Scope = User gesetzt werden
  3. In der app.xaml.cs lese ich den Wert der ConfigurationBase aus
  4. In der app.xaml.cs habe ich alle Variablen durch den ConfigurationBase-Wert ersetzt. Um die Werte zur Laufzeit zu ersetzen, mussten die Attribute auf Scopr = User gesetzt werden

Ich bin mit dieser Lösung nicht wirklich glücklich, da ich alle Attribute manuell ändern muss. Wenn ich ein neues Attribut hinzufüge, muss ich es in app.xaml.cs beachten.

Hier ein Code-Ausschnitt aus der App.xaml.cs:

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

UPDATE

Ich habe gerade eine Verbesserung gefunden (wieder ein Code-Snippet aus der 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);
    }
}

Die Ersetzungen funktionieren jetzt für alle Attribute in meinen Einstellungen, die Type = string und Scope = User haben. Ich glaube, ich mag es so.

UPDATE2

Offensichtlich ist das Festlegen von Scope = Application nicht erforderlich, wenn Sie die Eigenschaften durchlaufen.

0
anhoppe

Ich würde empfehlen, Matt Hamsmiths Lösung zu folgen. Wenn es sich um ein zu implementierendes Problem handelt, erstellen Sie eine Erweiterungsmethode, die diese im Hintergrund für die AppSettings-Klasse implementiert.

So etwas wie:

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

    }

Innerhalb der Methode durchsuchen Sie die DictionaryInfoConfigSection mit Linq und geben den Wert mit dem passenden Schlüssel zurück. Sie müssen die Konfigurationsdatei jedoch folgendermaßen aktualisieren:

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

Drei mögliche Lösungen

Ich weiß, dass ich zu spät zur Party komme. Ich habe nach neuen Lösungen für das Problem mit den variablen Konfigurationseinstellungen gesucht. Es gibt ein paar Antworten, die sich auf die Lösungen beziehen, die ich in der Vergangenheit verwendet habe, aber die meisten scheinen etwas verworren zu sein. Ich dachte, ich würde meine alten Lösungen anschauen und die Implementierungen zusammenstellen, damit es Leuten helfen könnte, die mit dem gleichen Problem zu kämpfen haben.

In diesem Beispiel habe ich die folgende App-Einstellung in einer Konsolenanwendung verwendet:

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

1. Verwenden Sie Umgebungsvariablen

Ich glaube, autocro autocro's answer hat es angesprochen. Ich mache nur eine Implementierung, die beim Erstellen oder Debuggen ausreichen sollte, ohne Visual Studio schließen zu müssen. Ich habe diese Lösung früher verwendet ...

  • Erstellen Sie ein Pre-Build-Ereignis, das die MSBuild-Variablen verwendet

    Warnung: Verwenden Sie eine Variable, die nicht einfach ersetzt werden kann. Verwenden Sie daher Ihren Projektnamen oder etwas Ähnliches als Variablennamen.

    SETX BaseDir "$(ProjectDir)"

  • Variablen zurücksetzen; mit etwas wie dem folgenden:

    mgebungsvariablen bei Stapelüberlauf aktualisieren

  • Verwenden Sie die Einstellung in Ihrem 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. Verwenden Sie die String-Interpolation:

  • Verwenden Sie die Funktion 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. Verwenden Sie eine statische Klasse. Dies ist die Lösung, die ich am häufigsten verwende.

  • Die Umsetzung

`

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

`

  • Die statische Klasse

`

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

`

Projektnummer:

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

Pre-Build-Event:

Projekteinstellungen -> Build Events

0
StormChild

Ich glaube nicht, dass Sie Variablen definieren und verwenden können, um appSettings-Schlüssel in einer Konfigurationsdatei zu definieren. Ich habe Verkettungen wie Sie immer in Code verwaltet.

0

Ich habe ein bisschen Probleme mit dem, was Sie wollen, aber Sie können den App-Einstellungen eine Überschreibungsdatei hinzufügen und diese Überschreibungsdatei auf Umgebungsebene einstellen.

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

Für den Rollout von Produkten, bei denen viele Elemente mit ähnlichen Werten konfiguriert werden müssen, verwenden wir kleine Konsolen-Apps, die die XML-Daten lesen und basierend auf den übergebenen Parametern aktualisieren. Diese werden dann vom Installationsprogramm aufgerufen, nachdem der Benutzer nach der Option gefragt wurde Benötigte Information.

0
cjk