Можно ли сделать что-то подобное в файлах app.config
или web.config
?
<appSettings>
<add key="MyBaseDir" value="C:\MyBase" />
<add key="Dir1" value="[MyBaseDir]\Dir1"/>
<add key="Dir2" value="[MyBaseDir]\Dir2"/>
</appSettings>
Затем я хочу получить доступ к Dir2 в своем коде, просто сказав:
ConfigurationManager.AppSettings["Dir2"]
Это поможет мне, когда я установлю свое приложение на разных серверах и в разных местах, где мне нужно будет изменить только ОДНУ запись во всем app.config
. (Я знаю, что могу управлять всей конкатенацией в коде, но я предпочитаю такой способ).
c#
variables
web-config
app-config
DeeStackOverflow
источник
источник
Ответы:
Хороший вопрос.
Я не думаю, что есть. Я считаю, что это было бы хорошо известно, если бы был простой способ, и я вижу, что Microsoft создает механизм в Visual Studio 2010 для развертывания различных файлов конфигурации для развертывания и тестирования.
Однако с учетом сказанного; Я обнаружил, что у вас в
ConnectionStrings
разделе есть своего рода заполнитель под названием «| DataDirectory |». Может, вы могли бы посмотреть, что там работает ...Вот фрагмент
machine.config
его показа:<connectionStrings> <add name="LocalSqlServer" connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" providerName="System.Data.SqlClient" /> </connectionStrings>
источник
Немного более сложная, но гораздо более гибкая альтернатива - создать класс, представляющий раздел конфигурации. В вашем
app.config
/web.config
файле вы можете иметь это:<?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>
Затем в вашем .NET-коде (я буду использовать C # в своем примере) вы можете создать два таких класса:
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); } } } }
Наконец, в программном коде вы можете получить доступ к своим
app.config
переменным, используя свои новые классы, следующим образом:DirectoryInfoConfigSection config = (DirectoryInfoConfigSection)ConfigurationManager.GetSection("DirectoryInfo"); String dir1Path = config.Directory.Directory1Resolved; // This value will equal "C:\MyBase\Dir1"
источник
Вы можете сделать это с помощью моей библиотеки Expansive . Также доступно на nuget здесь .
Он был разработан с учетом этого в качестве основного варианта использования.
Умеренный пример (использование AppSettings в качестве источника по умолчанию для расширения токена)
В 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>
Используйте метод расширения .Expand () для расширяемой строки:
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; connectionString.Expand() // returns "server=db01.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"
или
Используйте оболочку Dynamic ConfigurationManager «Config» следующим образом (явный вызов Expand () не требуется):
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;"
Расширенный пример 1 (использование AppSettings в качестве источника по умолчанию для расширения токена)
В 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>
Используйте метод расширения .Expand () для расширяемой строки:
var connectionString = ConfigurationManager.ConnectionStrings["Default"].ConnectionString; connectionString.Expand() // returns "server=db01-dev.mycompany.com;uid=uid;pwd=pwd;Initial Catalog=master;"
источник
Я думал, что только что увидел этот вопрос.
Короче говоря, нет, в конфигурации приложения нет интерполяции переменных.
У вас есть два варианта
источник
У вас есть несколько вариантов. Вы можете сделать это с помощью этапа сборки / развертывания, который обработает ваш файл конфигурации, заменив ваши переменные правильным значением.
Другой вариант - определить свой собственный раздел конфигурации, который поддерживает это. Например, представьте себе этот xml:
<variableAppSettings> <variables> <add key="@BaseDir" value="c:\Programs\Widget"/> </variables> <appSettings> <add key="PathToDir" value="@BaseDir\Dir1"/> </appSettings> </variableAppSettings>
Теперь вы можете реализовать это с помощью настраиваемых объектов конфигурации, которые будут обрабатывать замену переменных за вас во время выполнения.
источник
Обычно я пишу статический класс со свойствами для доступа к каждой из настроек моего 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(); } }
Обычно я также выполняю преобразование типов, когда это необходимо в этом классе. Это позволяет иметь типизированный доступ к вашей конфигурации, и если настройки меняются, вы можете редактировать их только в одном месте.
Обычно замена настроек этим классом относительно проста и обеспечивает гораздо большую ремонтопригодность.
источник
Вы можете использовать переменные среды в своем
app.config
для описываемого вами сценария.<configuration> <appSettings> <add key="Dir1" value="%MyBaseDir%\Dir1"/> </appSettings> </configuration>
Тогда вы можете легко получить путь с помощью:
var pathFromConfig = ConfigurationManager.AppSettings["Dir1"]; var expandedPath = Environment.ExpandEnvironmentVariables(pathFromConfig);
источник
Внутри
<appSettings>
вы можете создавать ключи приложений,<add key="KeyName" value="Keyvalue"/>
Позже вы можете получить доступ к этим значениям, используя:
ConfigurationManager.AppSettings["Keyname"]
источник
Я бы посоветовал вам DslConfig . С помощью DslConfig вы можете использовать иерархические файлы конфигурации из Global Config, Config per server host для настройки каждого приложения на каждом хосте сервера (см. AppSpike).
Если это
слишком сложно для вас, вы можете просто использовать глобальную конфигурацию Variables.var Просто настройте в Varibales.var
baseDir = "C:\MyBase" Var["MyBaseDir"] = baseDir Var["Dir1"] = baseDir + "\Dir1" Var["Dir2"] = baseDir + "\Dir2"
И получите значения конфигурации с помощью
Configuration config = new DslConfig.BooDslConfiguration() config.GetVariable<string>("MyBaseDir") config.GetVariable<string>("Dir1") config.GetVariable<string>("Dir2")
источник
Я не думаю, что вы можете объявлять и использовать переменные для определения ключей appSettings в файле конфигурации. Я всегда управлял конкатенациями в коде, как вы.
источник
Я немного борюсь с тем, что вы хотите, но вы можете добавить файл переопределения в настройки приложения, а затем установить этот файл переопределения для каждой среды.
<appSettings file="..\OverrideSettings.config">
источник
Для развертывания продуктов, в которых нам нужно настроить множество элементов с похожими значениями, мы используем небольшие консольные приложения, которые считывают XML и обновляют в соответствии с переданными параметрами. Затем они вызываются установщиком после того, как он запросит у пользователя Необходимая информация.
источник
Я бы рекомендовал следовать решению Мэтта Хамсмита. Если это проблема для реализации, то почему бы не создать метод расширения, который реализует это в фоновом режиме в классе AppSettings?
Что-то типа:
public static string GetValue(this NameValueCollection settings, string key) { }
Внутри метода вы выполняете поиск в DictionaryInfoConfigSection с помощью Linq и возвращаете значение с соответствующим ключом. Однако вам нужно будет обновить файл конфигурации до чего-то в этом роде:
<appSettings> <DirectoryMappings> <DirectoryMap key="MyBaseDir" value="C:\MyBase" /> <DirectoryMap key="Dir1" value="[MyBaseDir]\Dir1"/> <DirectoryMap key="Dir2" value="[MyBaseDir]\Dir2"/> </DirectoryMappings> </appSettings>
источник
Я придумал такое решение:
Я не очень доволен этим решением, потому что мне нужно изменить все атрибуты вручную, если я добавлю новый, я должен учитывать его в app.xaml.cs.
Вот фрагмент кода из App.xaml.cs:
string configBase = Settings.Default.ConfigurationBase; Settings.Default.CommonOutput_Directory = Settings.Default.CommonOutput_Directory.Replace("${ConfigurationBase}", configBase);
ОБНОВИТЬ
Только что нашел улучшение (снова фрагмент кода из 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); } }
Теперь замены работают для всех атрибутов в моих настройках, которые имеют Type = string и Scope = User. Думаю, мне это нравится.
ОБНОВЛЕНИЕ2
По-видимому, установка Scope = Application не требуется при запуске свойств.
источник
Три возможных решения
В этом примере я использовал следующую настройку в консольном приложении:
<appSettings> <add key="EnvironmentVariableExample" value="%BaseDir%\bin"/> <add key="StaticClassExample" value="bin"/> <add key="InterpollationExample" value="{0}bin"/> </appSettings>
1. Используйте переменные среды
Создайте событие перед сборкой, которое будет использовать переменные MSBuild
SETX BaseDir "$(ProjectDir)"
Сбросить переменные; используя что-то вроде следующего:
Обновить переменные среды при переполнении стека
Используйте настройку в своем коде:
'
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. Используйте строковую интерполяцию:
Используйте функцию 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. Использование статического класса. Это решение, которое я чаще всего использую.
Реализация
`
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; } } }
`
Код проекта:
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; } } } }
Событие перед сборкой:
Настройки проекта -> События сборки
источник