如何检查一个appSettings键是否存在?

168

如何检查应用程序配置项是否可用?

例如: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
}
9个回答

246

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
14
它抛出了“对象引用未设置为对象实例”的异常。 - Waqar Alamgir
3
不,这是错误的。如果在应用程序设置 XML 节点中不存在“myKey”,则代码会抛出异常。 - Gionata
3
如果您检查了IsNullOrEmpty,那么当您实际上有一个键具有空字符串值作为有效设置时,您的“键不存在”逻辑将运行。 - nrjohnstone
4
这不是最佳答案,因为它会引发异常。Divyesh Patel是更好的解决方案。 - VRPF
显示剩余6条评论

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

如果您之后没有使用该值,那么这可能会稍微更有效率一些。问题明确提到测试“是否可用应用程序设置”。由于“可用性”在我看来意味着有使用的愿望,所以我认为用户195488提供的答案对来到这里的人们更有用 - 但严格来说,您的答案也是正确的。 - Code Jockey
11
这个解决方案明显更好,因为它实际上检查了键是否存在。如果我的键有一个空值,user195488提供的解决方案将会给我一个错误的结果。 - dyslexicanaboko
9
这个解决方案是错误的。AppSettings是一个NameValueCollection类型,默认情况下在键查找时不区分大小写。但是,你在这里使用的LINQ .Contains扩展方法将默认使用区分大小写的比较方式。 - Jax
我喜欢这个,因为如果我发送的键名不存在,它会正确地工作并回答上面给出的引用空错误。 - Gorodeckij Dimitrij

10

通过泛型和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);

1
ConfigurationManager.AppSettings 不区分大小写,但 Any(key => key == MyKey) 是区分大小写的。 - janv8000
@janv8000 我需要区分大小写,但已更新示例以处理它。 - codebender
在进行大小写不敏感的比较时,使用ToUpper会更加快速(请参见https://dev59.com/b-o6XIcBkEYKwwoYTzRZ#12137)。更好的方法是使用string.Equals()重载并传递StringComparisonType。 - janv8000
这是一个非常好的解决方案。我稍微修改了实现以支持必需设置的概念。只有一件事 - 记得在你的类中添加 using System.ComponentModel; 语句以支持使用 TypeDescriptor 类。 - STLDev

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

2
如果你在配置文件中找不到你需要的键,就无法使用.ToString()将其转换为字符串,因为该值将为空,你会收到一个"Object reference not set to an instance of an object"错误。最好先检查该值是否存在,然后再尝试获取字符串表示形式。
if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings["myKey"]))
{
    String myKey = ConfigurationManager.AppSettings["myKey"].ToString();
}

或者,正如Code Monkey建议的那样:
if (ConfigurationSettings.AppSettings["myKey"] != null)
{
// Now do your magic..
}

2

我认为LINQ表达式可能是最好的选择:

   const string MyKey = "myKey"

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

当然可以...但我不知道 - 这种方法有什么优势吗?如果我真的精通Linq(大多数C#程序员最终可能会),那么阅读这个示例可能会和这种方法一样容易,但我不认为它会更容易 - 所以除非有效率上的优势...为什么要这样做呢? - Code Jockey
没有效率优势,而且在语法上冗长(依我看)。 - John Nicholas
1
ConfigurationManager.AppSettings 不区分大小写,但 Any(key => key == MyKey) 则是区分大小写的。 - janv8000

2

上面的选项给予了所有方式的灵活性,如果您知道关键字类型,请尝试解析它们。

bool.TryParse(ConfigurationManager.AppSettings["myKey"], out myvariable);

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;
  }

1
欢迎来到SO!当您发布答案时,请尽量解释一下您的解决方案。在这种情况下,有几个答案,请尝试在您的答案中揭示优点。 - David García Bodego

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接