Я искал здесь ответ. Прошу прощения, если это было задано раньше (как я подозреваю).
Сводка:. Как я могу строго набирать вызовы в свой web.config без дублирования имен свойств?
Детали: В моем коде я пытаюсь свести к минимуму использование строк, и мне не нравится определять что-то дважды.
Дополнением обоих этих выигрышей является мое ограничение использования AppSettings (и его строк) на один класс, который я ссылаюсь на весь проект. Класс AppSettings предоставляет публичные свойства:
12 public static string DateFormatString {
13 get {
14 return ConfigurationManager.AppSettings["DateFormatString"];
15 }
16 }
Как я могу сохранить этот класс и предотвратить дублирование (строки 12 и 14) имени свойства?
В качестве альтернативы, какое другое решение вы могли бы порекомендовать?
Мне нравится использовать пользовательские обработчики конфигурации.
http://haacked.com/archive/2007/03/12/custom-configuration-sections-in-3-easy-steps.aspx
В вашем примере нет дублирования: One DateFormatString - это имя свойства, а другое - строка. Вы просто следуете за соглашением, которое однозначно идентифицирует свойство для ключа поиска для значения.
Я вижу одно возможное улучшение. Вы должны прочитать конфигурационный файл один раз в статическом конструкторе и сохранить значения, а не читать их из AppSettings каждый раз при доступе к ресурсу.
Я написал пакет nuget, который делает это (между прочим). сопутствующий пост в блоге приводится в деталях, но этот упрощенный фрагмент показывает суть его как относящегося к вашему вопросу.
public string DateFormatString =>
ConfigurationManager.AppSettings[MethodBase.GetCurrentMethod().Name.Replace("get_", "")];
Одно решение может быть
public enum Settings
{
None,
DateFormatString,
DefeaultUserPrefix,
SomeOtherValue
}
а затем иметь вспомогательный класс, например,
public static class ConfigurationHelper
{
public static Get<T>(Settings setting)
{
string output = ConfigurationManager.AppSettings[setting.ToString()];
if(string.isNullOrEmpty(output))
throw new ConfigurationErrorsException("Setting " + setting + " is not defined in Configuration file.");
return (T)output; //You can probably use Convert.* functions.
}
}
Ваш код вызова будет выглядеть следующим образом:
ConfigurationHelper.Get<string>(Settings.DateFormatString);
Приведенный выше подход обеспечивает некоторый уровень сильного ввода, но вам все равно нужно убедиться, что имя параметра в файле конфигурации совпадает с именем перечисления.
Лучшим выбором будет автоматический генерация класса на основе файла конфигурации.
Если вам нужны строго типизированные свойства, вы можете написать
public static string DateFormatString
{
get { return ConfigurationHelper.Get<string>(Settings.DateFormatString); }
}
Кроме того, я бы советовал не читать конфигурационный файл в конструкторе (преждевременная оптимизация?). Если вы читаете конфигурационный файл в конструкторе, это означает, что вы не можете изменять файл конфигурации во время работы приложения.
Создайте свой собственный ConfigurationSection
с помощью Configuration Section Designer, таким образом вам не нужно использовать AppSettings
вообще... но у вас будет своя коллекция настроек, в которой даже будет Intellisense в файле web.config
.
Я бы рекомендовал десериализацию web.config в объекте. Затем вы можете получить доступ ко всем записям конфигурации, как если бы они были свойствами (не может быть гораздо более строго типизировано, чем это!)
Я создаю оболочку для всего, что не принадлежит мне напрямую. Это включает в себя кеш, сеанс, конфигурацию, внешние веб-службы и т.д. Это позволяет мне инкапсулировать грязные детали использования этого виджета. В случае конфигурации у меня есть класс конфигурации bare bones, который предоставляет различные свойства, в которых я разместил свой app.config или web.config. Это может выглядеть примерно так:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using RanchBuddy.Core.Services.Impl;
using StructureMap;
namespace RanchBuddy.Core.Services.Impl
{
[Pluggable("Default")]
public class ConfigurationService : IConfigurationService
{
internal static int GetDefaultCacheDuration_Days()
{
return Convert.ToInt32(ConfigurationManager.AppSettings["DefaultCacheDuration_Days"]);
}
...
internal static LoggingType GetLoggingType()
{
string loggingType = ConfigurationManager.AppSettings["LoggingType"].ToString();
if(loggingType.ToLower() == "verbose")
{
return LoggingType.Verbose;
}
else if (loggingType.ToLower() == "error")
{
return LoggingType.Error;
}
return LoggingType.Error;
}
...
public static string GetRoot()
{
string result = "";
if(ConfigurationManager.AppSettings["Root"] != null)
{
result = ConfigurationManager.AppSettings["Root"].ToString();
}
return result;
}
}
}
Внутри вы можете сделать больше, чем просто получить значения из файла конфигурации. Вы можете преобразовать строку в тип, который должен быть. Вы можете использовать строку для определения возвращаемого значения перечисления. И т.д. Но ключ заключается в том, что любые изменения, которые когда-либо должны быть сделаны относительно конфигурации, могут быть сделаны здесь. Чтобы включить, если вы хотите поменять механизм хранилища конфигурации!