Як перевірити, чи існує ключ 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
У нашій бібліотеці функція IsNull, що нагадує SQL, завдяки чому пошук налаштування дуже зручний:Dim configValue As String = Util.IsNull(ConfigurationManager.AppSettings.Get("SettingName"), String.Empty)
Ейрік Н

10
Це закидає "Посилання на об'єкт не встановлено на екземпляр об'єкта"
Waqar Alamgir

Ні, це неправильно Якщо "myKey" в налаштуваннях програми не існує вузла xml, код видав виняток.
Гіоната

якщо ви перевірите IsNullOrEmpty, ваша логіка для "ключа не існує" запуститься, якщо у вас дійсно є ключ із значенням пустого рядка як дійсне значення
nrjohnstone

3
не найкраща відповідь, оскільки це кидає винятки. Divyesh Patel - краще рішення.
VRPF

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

Це, мабуть, буде дещо ефективніше (?), Якби у вас не було бажання використовувати значення згодом. Питання конкретно зазначає тестування "чи доступна настройка програми". Оскільки доступність передбачає бажання використовувати його на увазі, я б сказав, що відповідь, надана користувачем195488, буде більш корисною для людей, які приїжджають сюди - але строго кажучи, ваша відповідь також є правильною.
Code Jockey

10
Це набагато краще рішення для простого факту, який насправді перевіряє, чи існує ключ. Якщо у мене для мого ключа є порожнє значення, рішення, надане користувачем195488, дасть мені помилковий позитив.
dislexicanaboko

6
Це рішення невірно. AppSettings - це NameValueCollection, який за замовчуванням нечутливий до регістру, коли мова заходить про ключові пошуки. Метод розширення LINQ .Contains, який ви використовуєте тут, за замовчуванням проведе порівняння з урахуванням регістру .
Jax

9

Безпечно повернене значення за замовчуванням за допомогою generics та 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 () перевантаження, передаючи StringComppareType.
janv8000

Це дійсно чудове рішення питання. Я трохи змінив реалізацію, щоб підтримати концепцію необхідних налаштувань. Тільки одне - не забудьте додати 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 #), тоді, мабуть , читати цей приклад буде так само просто , але я не думаю, що це буде простіше - тому, якщо немає переваги в ефективності ... чому?
Code Jockey

відсутність переваги ефективності та синтаксично багатослівний imo.
Джон Ніколас

1
ConfigurationManager.AppSettingsAny(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;
  }

Ласкаво просимо до SO! Коли ви публікуєте відповідь, будь ласка, спробуйте трохи пояснити своє рішення. У цьому випадку є ще кілька відповідей, спробуйте викрити плюси у своїх.
Давид Гарсія Бодего
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.