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
}
rower
źródło

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
}

źródło
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
}
Divyesh Patel
źródło
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);
kodebender
źródło
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"));
Johnny Trinh
źródło
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..
}
John Craft
źródło
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);

sam
źródło
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
          }
mike gold
źródło
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;
}
nimchimpsky
źródło
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;
  }
Reinier van de Wetering
źródło
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