Jak sprawdzić, czy istnieje klucz appSettings?


146

Jak sprawdzić, czy ustawienie aplikacji jest dostępne?

tj. app.config

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

oraz w pliku kodu

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

Odpowiedzi:


223

MSDN: Configuration Manager.AppSettings

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

lub

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

2
W naszej bibliotece mamy funkcję IsNull podobną do SQL, która sprawia, że ​​pobieranie ustawień jest bardzo przydatne:Dim configValue As String = Util.IsNull(ConfigurationManager.AppSettings.Get("SettingName"), String.Empty)
Eirik H

10
Zgłasza „Odniesienie do obiektu nie jest ustawione na instancję obiektu”
Waqar Alamgir,

Nie, to źle. Jeśli „myKey” nie istnieje w węźle xml ustawień aplikacji, kod zgłosił wyjątek.
Gionata

jeśli zaznaczysz IsNullOrEmpty, Twoja logika dla „klucza nie istnieje” będzie działać, gdy faktycznie masz klucz z pustą wartością ciągu jako prawidłowym ustawieniem
nrjohnstone.

3
nie najlepsza odpowiedź, ponieważ rzuca wyjątki. Divyesh Patel to lepsze rozwiązanie.
VRPF

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

Byłoby to prawdopodobnie bardziej wydajne (?), Gdybyś nie chciał później używać tej wartości. Pytanie konkretnie wspomina o testowaniu „czy ustawienie aplikacji jest dostępne”. Ponieważ dostępność sugeruje chęć korzystania z niej w mojej głowie, powiedziałbym, że odpowiedź udzielona przez user195488 będzie bardziej przydatna dla osób tu przyjeżdżających - ale ściśle mówiąc, twoja odpowiedź jest również poprawna.
Code Jockey,

10
Jest to znacznie lepsze rozwiązanie ze względu na prosty fakt, że faktycznie sprawdza, czy klucz istnieje. Jeśli mam pustą wartość dla mojego klucza, rozwiązanie dostarczone przez user195488 dałoby mi fałszywie dodatni wynik.
dyslexicanaboko

6
To rozwiązanie jest nieprawidłowe. AppSettings to NameValueCollection, która domyślnie nie rozróżnia wielkości liter, jeśli chodzi o wyszukiwanie kluczy. Metoda rozszerzenia LINQ .Contains, której tutaj używasz, będzie jednak domyślnie uwzględniać wielkość liter .
Jax

9

Bezpiecznie zwrócono wartość domyślną za pośrednictwem typów ogólnych i 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;
}

Używane w następujący sposób:

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

ConfigurationManager.AppSettingsnie rozróżnia wielkości liter, Any(key => key == MyKeyale jest
janv8000

@ janv8000 Chciałem rozróżniać wielkość liter, ale zaktualizowałem przykład, aby sobie z tym poradzić.
codebender

Prawidłowe porównania bez rozróżniania wielkości liter są szybsze w przypadku ToUpper (patrz stackoverflow.com/a/12137/389424 ). Jeszcze lepszym rozwiązaniem jest użycie przeciążenia string.Equals () przekazującego StringComparisonType.
janv8000

To naprawdę świetne rozwiązanie problemu. Zmodyfikowałem nieco implementację, aby wspierać koncepcję wymaganych ustawień. Tylko jedno - pamiętaj, aby dodać using System.ComponentModel;oświadczenie do swojej klasy, aby wspierać korzystanie z TypeDescriptorklasy.
STLDev

3
var isAlaCarte = 
    ConfigurationManager.AppSettings.AllKeys.Contains("IsALaCarte") && 
    bool.Parse(ConfigurationManager.AppSettings.Get("IsALaCarte"));

2

Jeśli szukanego klucza nie ma w pliku konfiguracyjnym, nie będzie można go przekonwertować na ciąg za pomocą .ToString (), ponieważ wartość będzie równa null i otrzymasz komunikat „Object reference not set do wystąpienia obiektu ”błąd. Najlepiej jest najpierw sprawdzić, czy wartość istnieje, zanim spróbujesz uzyskać reprezentację w postaci ciągu.

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

Lub, jak zasugerował Code Monkey:

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

2

Górne opcje dają elastyczność na wszystkie sposoby, jeśli znasz typ klucza, spróbuj je przeanalizować bool.TryParse(ConfigurationManager.AppSettings["myKey"], out myvariable);


2

Myślę, że wyrażenie LINQ może być najlepsze:

   const string MyKey = "myKey"

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

jasne ... ale idunno - czy jest jakaś zaleta tej metody? Jeśli NAPRAWDĘ dobrze zorientowałem się w Linq (którym prawdopodobnie w końcu będzie większość programistów C #), to prawdopodobnie byłby tak łatwy do odczytania tego przykładu, ale nie sądzę, żeby to kiedykolwiek było łatwiejsze - więc chyba że ma przewagę wydajności ... czemu?
Code Jockey,

brak korzyści w zakresie wydajności i składniowo pełne imo.
John Nicholas

1
ConfigurationManager.AppSettingsnie rozróżnia wielkości liter, Any(key => key == MyKeyale jest
janv8000

1

Podobała mi się odpowiedź codebender , ale potrzebowałem jej do pracy w C ++ / CLI. Na tym skończyłem. Nie ma użycia LINQ, ale działa.

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

Użycie nowej składni C # z TryParse działało dobrze dla mnie:

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

Witamy w SO! Kiedy piszesz odpowiedź, spróbuj trochę wyjaśnić swoje rozwiązanie. W tym przypadku jest jeszcze kilka odpowiedzi, spróbuj ujawnić zalety w swoich.
David García Bodego
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.