Как проверить, существует ли ключ appSettings?


146

Как проверить, доступна ли настройка приложения?

то есть app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key ="someKey" value="someValue"/>
  </appSettings>
</configuration>

и в кодовом файле

if (ConfigurationManager.AppSettings.ContainsKey("someKey"))
{
  // Do Something
}else{
  // Do Something Else
}

Ответы:


223

MSDN: Configuration Manager.AppSettings

if (ConfigurationManager.AppSettings[name] != null)
{
// Now do your magic..
}

или

string s = ConfigurationManager.AppSettings["myKey"];
if (!String.IsNullOrEmpty(s))
{
    // Key exists
}
else
{
    // Key doesn't exist
}

2
В нашей библиотеке есть SQL-подобная функция IsNull, которая делает получение параметров очень удобным:Dim configValue As String = Util.IsNull(ConfigurationManager.AppSettings.Get("SettingName"), String.Empty)
Eirik H

10
Он выдает «Ссылка на объект не установлена ​​для экземпляра объекта»
Вакар Аламгир

Нет, это не так. Если «myKey» не существует в xml-узле настроек приложения, код выдает исключение.
Гионата

если вы проверите IsNullOrEmpty, тогда ваша логика «ключ не существует» будет работать, когда у вас фактически есть ключ с пустым строковым значением в качестве допустимой установки
nrjohnstone

3
не самый лучший ответ, поскольку это создает исключения. Дивьеш Патель - лучшее решение.
VRPF

81
if (ConfigurationManager.AppSettings.AllKeys.Contains("myKey"))
{
    // Key exists
}
else
{
    // Key doesn't exist
}

Вероятно, это было бы немного более эффективно (?), Если бы у вас не было желания использовать значение впоследствии. В частности, в вопросе упоминается проверка «доступна ли настройка приложения». Поскольку доступность подразумевает желание использовать ее в моем сознании, я бы сказал, что ответ пользователя 195488 будет более полезным для людей, которые приходят сюда, но, строго говоря, ваш ответ также верен.
Код жокея

10
Это гораздо лучшее решение для простого факта, что он фактически проверяет, существует ли ключ. Если у меня есть пустое значение для моего ключа, решение, предоставленное user195488, даст мне ложное срабатывание.
дислексиканабоко

6
Это решение неверно. AppSettings - это NameValueCollection, которая по умолчанию нечувствительна к регистру, когда дело доходит до поиска ключей. Используемый здесь метод расширения LINQ .Contains, однако, по умолчанию сравнивается с учетом регистра .
Jax

9

Безопасно вернул значение по умолчанию через дженерики и LINQ.

public T ReadAppSetting<T>(string searchKey, T defaultValue, StringComparison compare = StringComparison.Ordinal)
{
    if (ConfigurationManager.AppSettings.AllKeys.Any(key => string.Compare(key, searchKey, compare) == 0)) {
        try
        { // see if it can be converted.
            var converter = TypeDescriptor.GetConverter(typeof(T));
            if (converter != null) defaultValue = (T)converter.ConvertFromString(ConfigurationManager.AppSettings.GetValues(searchKey).First());
        }
        catch { } // nothing to do just return the defaultValue
    }
    return defaultValue;
}

Используется следующим образом:

string LogFileName = ReadAppSetting("LogFile","LogFile");
double DefaultWidth = ReadAppSetting("Width",1280.0);
double DefaultHeight = ReadAppSetting("Height",1024.0);
Color DefaultColor = ReadAppSetting("Color",Colors.Black);

ConfigurationManager.AppSettingsне чувствителен к регистру, Any(key => key == MyKeyоднако
janv8000

@ janv8000 Я хотел, чтобы чувствительность к регистру, но обновил пример, чтобы справиться с этим.
Codebender

Надлежащие сравнения без учета регистра быстрее с ToUpper (см. Stackoverflow.com/a/12137/389424 ). Еще лучше использовать перегрузку string.Equals (), передающую StringComparisonType.
января

Это действительно отличное решение проблемы. Я немного изменил реализацию, чтобы поддержать концепцию необходимых настроек. Только одно - не забудьте добавить using System.ComponentModel;оператор в ваш класс для поддержки использования TypeDescriptorкласса.
STLDev


2

Если искомый ключ отсутствует в файле конфигурации, вы не сможете преобразовать его в строку с помощью .ToString (), поскольку значение будет нулевым, и вы получите «Ссылка на объект не установлена» к экземпляру объекта "ошибка. Лучше сначала проверить, существует ли значение, прежде чем пытаться получить строковое представление.

if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["myKey"]))
{
    String myKey = ConfigurationManager.AppSettings["myKey"].ToString();
}

Или, как предложил Code Monkey:

if (ConfigurationSettings.AppSettings["myKey"] != null)
{
// Now do your magic..
}

2

Верхние параметры дают гибкость во всех отношениях, если вы знаете тип ключа, попробуйте их проанализировать bool.TryParse(ConfigurationManager.AppSettings["myKey"], out myvariable);


2

Я думаю, что выражение LINQ может быть лучшим:

   const string MyKey = "myKey"

   if (ConfigurationManager.AppSettings.AllKeys.Any(key => key == MyKey))
          {
              // Key exists
          }

конечно ... но idunno - есть ли преимущество этого метода? Если я ДЕЙСТВИТЕЛЬНО хорошо разбираюсь в Linq (что, вероятно, в конечном итоге и придет большинство программистов на C #), то этот пример, вероятно, будет так же легко прочитать, но я не думаю, что когда-либо будет легче - так что если нет преимущества в эффективности ... Зачем?
Код жокея

нет преимущества в эффективности и синтаксически многословно.
Джон Николас

1
ConfigurationManager.AppSettingsне чувствителен к регистру, Any(key => key == MyKeyоднако
janv8000

1

Мне понравился ответ codebender , но он нужен для работы в C ++ / CLI. Это то, что я закончил. Там нет использования LINQ, но работает.

generic <typename T> T MyClass::ReadAppSetting(String^ searchKey, T defaultValue) {
  for each (String^ setting in ConfigurationManager::AppSettings->AllKeys) {
    if (setting->Equals(searchKey)) { //  if the key is in the app.config
      try {                           // see if it can be converted
        auto converter = TypeDescriptor::GetConverter((Type^)(T::typeid)); 
        if (converter != nullptr) { return (T)converter->ConvertFromString(ConfigurationManager::AppSettings[searchKey]); }
      } catch (Exception^ ex) {} // nothing to do
    }
  }
  return defaultValue;
}

0

Использование нового синтаксиса c # с TryParse хорошо для меня:

  // TimeOut
  if (int.TryParse(ConfigurationManager.AppSettings["timeOut"], out int timeOut))
  {
     this.timeOut = timeOut;
  }

Добро пожаловать на ТАК! Когда вы отправляете ответ, пожалуйста, попробуйте немного объяснить свое решение. В этом случае есть еще несколько ответов, попробуйте выставить плюсы в свой.
Дэвид Гарсия Бодего
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.