Apakah mungkin untuk melakukan sesuatu seperti berikut di file app.config
atau web.config
?
<appSettings>
<add key="MyBaseDir" value="C:\MyBase" />
<add key="Dir1" value="[MyBaseDir]\Dir1"/>
<add key="Dir2" value="[MyBaseDir]\Dir2"/>
</appSettings>
Saya kemudian ingin mengakses Dir2 di kode saya hanya dengan mengatakan:
ConfigurationManager.AppSettings["Dir2"]
Ini akan membantu saya ketika saya menginstal aplikasi saya di server dan lokasi yang berbeda di mana saya hanya perlu mengubah SATU entri di seluruh saya app.config
. (Saya tahu saya bisa mengatur semua penggabungan dalam kode, tapi saya lebih suka dengan cara ini).
c#
variables
web-config
app-config
DeeStackOverflow
sumber
sumber
Jawaban:
Pertanyaan bagus.
Saya rasa tidak ada. Saya percaya ini akan cukup terkenal jika ada cara yang mudah, dan saya melihat bahwa Microsoft sedang membuat mekanisme dalam Visual Studio 2010 untuk menyebarkan file konfigurasi yang berbeda untuk penyebaran dan pengujian.
Namun demikian; Saya telah menemukan bahwa Anda di
ConnectionStrings
bagian ini memiliki semacam placeholder yang disebut "| DataDirectory |". Mungkin Anda bisa melihat apa yang sedang dikerjakan di sana ...Ini adalah bagian dari
machine.config
menunjukkannya:<connectionStrings> <add name="LocalSqlServer" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" /> </connectionStrings>
sumber
Alternatif yang sedikit lebih rumit, tetapi jauh lebih fleksibel, adalah membuat kelas yang mewakili bagian konfigurasi. Di
app.config
/web.config
file Anda, Anda dapat memiliki ini:<?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>
Kemudian, dalam kode .NET Anda (saya akan menggunakan C # dalam contoh saya), Anda dapat membuat dua kelas seperti ini:
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); } } } }
Terakhir, dalam kode program Anda, Anda dapat mengakses
app.config
variabel Anda , menggunakan kelas baru Anda, dengan cara ini:DirectoryInfoConfigSection config = (DirectoryInfoConfigSection)ConfigurationManager.GetSection("DirectoryInfo"); String dir1Path = config.Directory.Directory1Resolved; // This value will equal "C:\MyBase\Dir1"
sumber
Anda dapat menyelesaikannya menggunakan perpustakaan saya yang Luas . Juga tersedia di nuget disini .
Ini dirancang dengan ini sebagai kasus penggunaan utama.
Contoh Sedang (menggunakan AppSettings sebagai sumber default untuk perluasan token)
Di app.config:
<configuration> <appSettings> <add key="Domain" value="mycompany.com"/> <add key="ServerName" value="db01.{Domain}"/> </appSettings> <connectionStrings> <add name="Default" connectionString="server={ServerName};uid=uid;pwd=pwd;Initial Catalog=master;" provider="System.Data.SqlClient" /> </connectionStrings> </configuration>
Gunakan metode ekstensi .Expand () pada string yang akan diperluas:
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; connectionString.Expand() // returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"
atau
Gunakan pembungkus Dynamic ConfigurationManager "Config" sebagai berikut (Panggilan eksplisit ke Perluas () tidak diperlukan):
var serverName = Config.AppSettings.ServerName; // returns "db01.mycompany.com" var connectionString = Config.ConnectionStrings.Default; // returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"
Contoh Lanjutan 1 (menggunakan AppSettings sebagai sumber default untuk perluasan token)
Di app.config:
<configuration> <appSettings> <add key="Environment" value="dev"/> <add key="Domain" value="mycompany.com"/> <add key="UserId" value="uid"/> <add key="Password" value="pwd"/> <add key="ServerName" value="db01-{Environment}.{Domain}"/> <add key="ReportPath" value="\\{ServerName}\SomeFileShare"/> </appSettings> <connectionStrings> <add name="Default" connectionString="server={ServerName};uid={UserId};pwd={Password};Initial Catalog=master;" provider="System.Data.SqlClient" /> </connectionStrings> </configuration>
Gunakan metode ekstensi .Expand () pada string yang akan diperluas:
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; connectionString.Expand() // returns "server=db01-dev.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"
sumber
Saya pikir saya baru saja melihat pertanyaan ini.
Singkatnya, tidak, tidak ada interpolasi variabel dalam konfigurasi aplikasi.
Anda punya dua pilihan
sumber
Anda memiliki dua pilihan. Anda dapat melakukan ini dengan langkah build / deploy yang akan memproses file konfigurasi Anda dengan mengganti variabel Anda dengan nilai yang benar.
Pilihan lain adalah menentukan bagian Konfigurasi Anda sendiri yang mendukung ini. Misalnya bayangkan xml ini:
<variableAppSettings> <variables> <add key="@BaseDir" value="c:\Programs\Widget"/> </variables> <appSettings> <add key="PathToDir" value="@BaseDir\Dir1"/> </appSettings> </variableAppSettings>
Sekarang Anda akan menerapkan ini menggunakan objek konfigurasi khusus yang akan menangani penggantian variabel untuk Anda pada waktu proses.
sumber
Biasanya, saya akhirnya menulis kelas statis dengan properti untuk mengakses setiap pengaturan web.config saya.
public static class ConfigManager { public static string MyBaseDir { return ConfigurationManager.AppSettings["MyBaseDir"].toString(); } public static string Dir1 { return MyBaseDir + ConfigurationManager.AppSettings["Dir1"].toString(); } }
Biasanya, saya juga melakukan konversi tipe saat diminta di kelas ini. Ini memungkinkan untuk memiliki akses yang diketik ke konfigurasi Anda, dan jika pengaturan berubah, Anda dapat mengeditnya hanya di satu tempat.
Biasanya, mengganti pengaturan dengan kelas ini relatif mudah dan memberikan kemudahan pemeliharaan yang jauh lebih besar.
sumber
Anda dapat menggunakan variabel lingkungan dalam
app.config
skenario yang Anda gambarkan<configuration> <appSettings> <add key="Dir1" value="%MyBaseDir%\Dir1"/> </appSettings> </configuration>
Kemudian Anda bisa dengan mudah mendapatkan jalur dengan:
var pathFromConfig = ConfigurationManager.AppSettings["Dir1"]; var expandedPath = Environment.ExpandEnvironmentVariables(pathFromConfig);
sumber
Di dalamnya
<appSettings>
Anda dapat membuat kunci aplikasi,<add key="KeyName" value="Keyvalue"/>
Nanti Anda dapat mengakses nilai-nilai ini menggunakan:
ConfigurationManager.AppSettings["Keyname"]
sumber
Saya sarankan Anda DslConfig . Dengan DslConfig Anda dapat menggunakan file konfigurasi hierarki dari Global Config, Config per host server untuk mengkonfigurasi per aplikasi pada setiap host server (lihat AppSpike).
Jika ini menjadi rumit bagi Anda, Anda cukup menggunakan konfigurasi global Variables.var.
Cukup konfigurasikan di Varibales.var
baseDir = "C:\MyBase" Var["MyBaseDir"] = baseDir Var["Dir1"] = baseDir + "\Dir1" Var["Dir2"] = baseDir + "\Dir2"
Dan dapatkan nilai konfigurasi dengan
Configuration config = new DslConfig.BooDslConfiguration() config.GetVariable<string>("MyBaseDir") config.GetVariable<string>("Dir1") config.GetVariable<string>("Dir2")
sumber
Saya rasa Anda tidak dapat mendeklarasikan dan menggunakan variabel untuk menentukan kunci appSettings dalam file konfigurasi. Saya selalu mengelola penggabungan dalam kode seperti Anda.
sumber
Saya sedikit kesulitan dengan apa yang Anda inginkan, tetapi Anda dapat menambahkan file override ke pengaturan aplikasi kemudian mengatur file override tersebut berdasarkan lingkungan.
<appSettings file="..\OverrideSettings.config">
sumber
Untuk meluncurkan produk di mana kami perlu mengonfigurasi banyak item dengan nilai yang serupa, kami menggunakan aplikasi konsol kecil yang membaca XML dan memperbarui berdasarkan parameter yang diteruskan. Ini kemudian dipanggil oleh penginstal setelah meminta pengguna untuk informasi yang dibutuhkan.
sumber
Saya akan merekomendasikan mengikuti solusi Matt Hamsmith. Jika ini adalah masalah untuk diterapkan, mengapa tidak membuat metode ekstensi yang mengimplementasikannya di latar belakang kelas AppSettings?
Sesuatu seperti:
public static string GetValue(this NameValueCollection settings, string key) { }
Di dalam metode Anda mencari melalui DictionaryInfoConfigSection menggunakan Linq dan mengembalikan nilai dengan kunci yang cocok. Anda harus memperbarui file konfigurasi, ke sesuatu di sepanjang baris ini:
<appSettings> <DirectoryMappings> <DirectoryMap key="MyBaseDir" value="C:\MyBase" /> <DirectoryMap key="Dir1" value="[MyBaseDir]\Dir1"/> <DirectoryMap key="Dir2" value="[MyBaseDir]\Dir2"/> </DirectoryMappings> </appSettings>
sumber
Saya datang dengan solusi ini:
Saya tidak terlalu senang dengan solusi ini karena saya harus mengubah semua atribut secara manual, jika saya menambahkan yang baru, saya harus mempertimbangkannya di app.xaml.cs.
Berikut cuplikan kode dari App.xaml.cs:
string configBase = Settings.Default.ConfigurationBase; Settings.Default.CommonOutput_Directory = Settings.Default.CommonOutput_Directory.Replace("${ConfigurationBase}", configBase);
MEMPERBARUI
Baru saja menemukan peningkatan (sekali lagi cuplikan kode dari 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); } }
Sekarang penggantian berfungsi untuk semua atribut dalam pengaturan saya yang memiliki Type = string dan Scope = User. Saya rasa saya suka seperti ini.
UPDATE2
Rupanya pengaturan Scope = Aplikasi tidak diperlukan saat menjalankan properti.
sumber
Tiga Solusi yang Mungkin
Untuk contoh ini saya telah menggunakan pengaturan aplikasi berikut di aplikasi konsol:
<appSettings> <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/> <add key="StaticClassExample" value="bin"/> <add key="InterpollationExample" value="{0}bin"/> </appSettings>
1. Gunakan variabel lingkungan
Buat acara pra-bangun yang akan menggunakan variabel MSBuild
SETX BaseDir "$(ProjectDir)"
Setel ulang variabel; menggunakan sesuatu seperti berikut:
Segarkan Variabel Lingkungan di Stack Overflow
Gunakan pengaturan di kode Anda:
'
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. Gunakan interpolasi string:
Gunakan fungsi 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. Menggunakan kelas statis, Ini adalah solusi yang paling sering saya gunakan.
Pelaksanaan
`
private void Test_Static_Class() { Console.WriteLine($"Using a static config class {Configuration.BinPath}"); }
`
Kelas statis
`
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; } } }
`
Kode proyek:
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; } } } }
Acara pra-bangun:
Pengaturan Proyek -> Acara Bangun
sumber