Переменные в app.config / web.config

Можно ли сделать что-то вроде следующего в файлах app.config или web.config ?

      

Затем я хочу получить доступ к Dir2 в своем коде, просто сказав:

  ConfigurationManager.AppSettings["Dir2"] 

Это поможет мне, когда я установлю свое приложение на разных серверах и в местах, где мне нужно будет только изменить одну запись в моем приложении app.config . (Я знаю, что могу управлять всеми конкатенациями в коде, но я предпочитаю это таким образом).

Хороший вопрос.

Я не думаю, что есть. Я считаю, что было бы хорошо известно, был ли простой способ, и я вижу, что Microsoft создает механизм в Visual Studio 2010 для развертывания различных файлов конфигурации для развертывания и тестирования.

С этим сказано, однако; Я обнаружил, что у вас в разделе ConnectionStrings есть своего рода заполнитель, называемый «| DataDirectory |». Может быть, вы могли бы посмотреть, что там работает …

Вот fragment из machine.config :

     

Несколько более сложной, но более гибкой альтернативой является создание classа, представляющего раздел конфигурации. В файле app.config / web.config вы можете:

     

Затем в вашем .NET-коде (я буду использовать C # в моем примере) вы можете создать два classа:

 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 , используя ваши новые classы, таким образом:

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

Вы можете использовать мою библиотеку Expansive: http://nuget.org/List/Packages/Expansive Source можно найти здесь: https://github.com/anderly/Expansive

Я думал, что только что увидел этот вопрос.

Короче говоря, нет, нет никакой интерполяции переменных в конфигурации приложения.

У вас есть два варианта

  1. Вы можете сворачивать свои собственные, чтобы заменить переменные во время выполнения
  2. Во время сборки массируйте конфигурацию приложения в соответствии с конкретными особенностями целевой среды развертывания. Некоторые подробности об этом при рассмотрении конфигурации – кошмар

У вас есть несколько вариантов. Вы можете сделать это с помощью шага сборки / развертывания, который обработает ваш файл конфигурации, заменив ваши переменные на правильное значение.

Другой вариант – определить ваш собственный раздел конфигурации, который поддерживал это. Например, представьте это xml:

         

Теперь вы реализуете это, используя пользовательские объекты конфигурации, которые будут обрабатывать замену переменных для вас во время выполнения.

Обычно я пишу статический class со свойствами для доступа к каждому из параметров моего 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(); } } 

Обычно, я также делаю преобразования типов, когда это требуется в этом classе. Он позволяет иметь типизированный доступ к вашей конфигурации, и если настройки меняются, вы можете редактировать их только в одном месте.

Обычно замена настроек этим classом относительно проста и обеспечивает гораздо большую ремонтопригодность.

Я бы предложил вам DslConfig . С помощью DslConfig вы можете использовать иерархические файлы конфигурации из Global Config, Config для каждого хоста сервера для конфигурации для каждого приложения на каждом сервере (см. 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("MyBaseDir") config.GetVariable("Dir1") config.GetVariable("Dir2") 

Вы можете использовать переменные среды в app.config для описанного вами сценария

      

Затем вы можете легко получить путь:

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

Я не думаю, что вы можете объявлять и использовать переменные для определения ключей appSettings в файле конфигурации. Я всегда управлял конкатенациями в коде, как вы.

Я немного борюсь с тем, что вы хотите, но вы можете добавить файл переопределения в настройки приложения, а затем установить этот файл переопределения для каждого окружения.

  

Для развертывания продуктов, где нам нужно настроить множество элементов с одинаковыми значениями, мы используем небольшие консольные приложения, которые читают XML и обновляют на основе переданных параметров. Затем они вызывается установщиком после того, как он попросил пользователя Необходимая информация.

Я бы порекомендовал вам решение Мэтта Хамсмита. Если это проблема для реализации, то почему бы не создать метод расширения, который реализует это в фоновом режиме в classе AppSettings?

Что-то вроде:

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

Внутри метода вы просматриваете DictionaryInfoConfigSection с помощью Linq и возвращаете значение с помощью соответствующего ключа. Вам нужно будет обновить конфигурационный файл, но что-то вроде этого:

        

Внутри вы можете создавать ключи приложения,

  

Позже вы можете получить доступ к этим значениям, используя:

 ConfigurationManager.AppSettings["Keyname"] 

Я придумал это решение:

  1. В приложении Settings.settings я определил переменную ConfigurationBase (с типом = строка Scope = Application)
  2. Я ввел переменную в целевые атрибуты в Settings.settings, все эти атрибуты должны были быть установлены в Scope = User
  3. В app.xaml.cs я считываю значение, если ConfigurationBase
  4. В app.xaml.cs я заменил все переменные значением ConfigurationBase. Чтобы заменить значения во время выполнения, атрибуты должны были быть установлены на Scopr = User

Я не очень доволен этим решением, потому что мне нужно вручную изменить все атрибуты, если я добавлю новый, который я должен рассмотреть в app.xaml.cs.

Здесь fragment кода из App.xaml.cs:

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

ОБНОВИТЬ

Просто нашел улучшение (опять-таки fragment кода из 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. Думаю, мне это нравится.

UPDATE2

Очевидно, что установка Scope = Application не требуется при работе над свойствами.

Три возможных решения

Я знаю, что опаздываю на вечеринку, я искал, были ли новые решения проблемы с параметрами конфигурации. Есть несколько ответов, которые касаются решений, которые я использовал в прошлом, но большинство из них немного запутано. Я думал, что посмотрю на свои старые решения и объединил реализации, чтобы они могли помочь людям, которые борются с одной и той же проблемой.

В этом примере я использовал следующую настройку приложения в консольном приложении:

      

1. Используйте переменные среды

Я считаю, что ответ autocro autocro коснулся этого. Я просто выполняю реализацию, которая должна быть достаточной при построении или отладке без необходимости закрывать визуальную студию. Я использовал это решение в тот же день …

  • Создайте событие предварительной сборки, которое будет использовать переменные 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. Используя статический class, это решение, которое я использую в основном.

  • Реализация

`

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

`

  • Статический class

`

 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:

            

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

Событие предварительной сборки:

Настройки проекта -> События сборки

  • Как получить имя переменной в виде строки?
  • Захват вывода нескольких строк в переменную Bash
  • Угловой - общий сервис между компонентами не работает
  • Неявная типизация; почему только локальные переменные?
  • объявить глобальную собственность в QML для других файлов QML
  • Лучше ли в C ++ проходить по значению или передавать постоянную ссылку?
  • Как разбить одну строку на несколько переменных в оболочке bash?
  • Как установить переменные в сценариях HIVE
  • Значение переменной доступа с использованием строки, представляющей имя переменной в C ++
  • Привязать к переменной массива bash косвенно, динамически сконструированным именем переменной
  • Локальное хранение в Угловом 2
  • Давайте будем гением компьютера.