【问题标题】:Multiple values for a single config key单个配置键的多个值
【发布时间】:2011-02-18 16:23:44
【问题描述】:

我正在尝试使用 ConfigurationManager.AppSettings.GetValues() 检索单个键的多个配置值,但我总是收到一个仅包含最后一个值的数组。我的appsettings.config 看起来像

<add key="mykey" value="A"/>
<add key="mykey" value="B"/>
<add key="mykey" value="C"/>

我正在尝试访问

ConfigurationManager.AppSettings.GetValues("mykey");

但我只收到{ "C" }

关于如何解决这个问题的任何想法?

【问题讨论】:

    标签: .net asp.net configuration


    【解决方案1】:

    你想做的事是不可能的。您要么必须以不同的方式命名每个键,要么执行 value="A,B,C" 之类的操作并在代码 string values = value.split(',') 中分离出不同的值。

    它将始终获取最后定义的键的值(在您的示例 C 中)。

    【讨论】:

      【解决方案2】:

      试试

      <add key="mykey" value="A,B,C"/>
      

      还有

      string[] mykey = ConfigurationManager.AppSettings["mykey"].Split(',');
      

      【讨论】:

      • 那么ConfigurationManager.AppSettings.GetValues() 有什么意义呢?
      • @Yuck 对底层 NameValueCollection 类的观点提出了质疑——它支持每个键的多个值,但实际上并不允许您为每个键设置多个值(AppSettings 必须在内部使用设置索引器)——这是问题的真正原因,而不是 GetValues() 只返回一个值。
      • 如果只有单个值,是否出现任何字符未找到错误?
      【解决方案3】:

      配置文件将每一行视为一个作业,这就是为什么您只看到最后一行。当它读取配置时,它会为您的键分配值“A”,然后是“B”,然后是“C”,并且由于“C”是最后一个值,所以它就是那个值。

      正如@Kevin 建议的那样,最好的方法可能是一个值,它的内容是一个可以解析的 CSV。

      【讨论】:

        【解决方案4】:

        我认为,您可以使用自定义配置部分http://www.4guysfromrolla.com/articles/032807-1.aspx

        【讨论】:

          【解决方案5】:

          由于ConfigurationManager.AppSettings.GetValues() 方法不起作用,我使用了以下解决方法来获得类似的效果,但需要使用唯一索引为键添加后缀。

          var name = "myKey";
          var uniqueKeys = ConfigurationManager.AppSettings.Keys.OfType<string>().Where(
              key => key.StartsWith(name + '[', StringComparison.InvariantCultureIgnoreCase)
          );
          var values = uniqueKeys.Select(key => ConfigurationManager.AppSettings[key]);
          

          这将匹配 myKey[0]myKey[1] 之类的键。

          【讨论】:

          • ConfigurationManager.ConnectionStrings 使您能够遍历一个列表,该列表否定此问题的所有答案(我知道它不是连接字符串,但您可以这样使用它)
          【解决方案6】:

          我知道我迟到了,但我找到了这个解决方案,而且效果很好,所以我只想分享。

          一切都是为了定义你自己的ConfigurationElement

          namespace Configuration.Helpers
          {
              public class ValueElement : ConfigurationElement
              {
                  [ConfigurationProperty("name", IsKey = true, IsRequired = true)]
                  public string Name
                  {
                      get { return (string) this["name"]; }
                  }
              }
          
              public class ValueElementCollection : ConfigurationElementCollection
              {
                  protected override ConfigurationElement CreateNewElement()
                  {
                      return new ValueElement();
                  }
          
          
                  protected override object GetElementKey(ConfigurationElement element)
                  {
                      return ((ValueElement)element).Name;
                  }
              }
          
              public class MultipleValuesSection : ConfigurationSection
              {
                  [ConfigurationProperty("Values")]
                  public ValueElementCollection Values
                  {
                      get { return (ValueElementCollection)this["Values"]; }
                  }
              }
          }
          

          在 app.config 中使用你的新部分:

          <configSections>
              <section name="PreRequest" type="Configuration.Helpers.MultipleValuesSection,
              Configuration.Helpers" requirePermission="false" />
          </configSections>
          
          <PreRequest>
              <Values>
                  <add name="C++"/>
                  <add name="Some Application"/>
              </Values>
          </PreRequest>
          

          当像这样检索数据时:

          var section = (MultipleValuesSection) ConfigurationManager.GetSection("PreRequest");
          var applications = (from object value in section.Values
                              select ((ValueElement)value).Name)
                              .ToList();
          

          最后感谢原作者post

          【讨论】:

            【解决方案7】:

            这里是完整的解决方案: aspx.cs 中的代码

            namespace HelloWorld
            {
                public partial class _Default : Page
                {
                    protected void Page_Load(object sender, EventArgs e)
                    {
                        UrlRetrieverSection UrlAddresses = (UrlRetrieverSection)ConfigurationManager.GetSection("urlAddresses");
                    }
                }
            
                public class UrlRetrieverSection : ConfigurationSection
                {
                    [ConfigurationProperty("", IsDefaultCollection = true,IsRequired =true)]
                    public UrlCollection UrlAddresses
                    {
                        get
                        {
                            return (UrlCollection)this[""];
                        }
                        set
                        {
                            this[""] = value;
                        }
                    }
                }
            
            
                public class UrlCollection : ConfigurationElementCollection
                {
                    protected override ConfigurationElement CreateNewElement()
                    {
                        return new UrlElement();
                    }
                    protected override object GetElementKey(ConfigurationElement element)
                    {
                        return ((UrlElement)element).Name;
                    }
                }
            
                public class UrlElement : ConfigurationElement
                {
                    [ConfigurationProperty("name", IsRequired = true, IsKey = true)]
                    public string Name
                    {
                        get
                        {
                            return (string)this["name"];
                        }
                        set
                        {
                            this["name"] = value;
                        }
                    }
            
                    [ConfigurationProperty("url", IsRequired = true)]
                    public string Url
                    {
                        get
                        {
                            return (string)this["url"];
                        }
                        set
                        {
                            this["url"] = value;
                        }
                    }
            
                }
            }
            

            在网络配置中

            <configSections>
               <section name="urlAddresses" type="HelloWorld.UrlRetrieverSection" />
            </configSections>
            <urlAddresses>
                <add name="Google" url="http://www.google.com" />
               <add name="Yahoo"  url="http://www.yahoo.com" />
               <add name="Hotmail" url="http://www.hotmail.com/" />
            </urlAddresses>
            

            【讨论】:

            • 感谢 CubeJockey 重新调整。
            【解决方案8】:

            我对 JJS 回复的看法: 配置文件:

            <?xml version="1.0" encoding="utf-8" ?>
            <configuration>
              <configSections>
                <section name="List1" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
                <section name="List2" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
              </configSections>
                <startup> 
                    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
                </startup>
              <List1>
                <add key="p-Teapot" />
                <add key="p-drongo" />
                <add key="p-heyho" />
                <add key="p-bob" />
                <add key="p-Black Adder" />
              </List1>
              <List2>
                <add key="s-Teapot" />
                <add key="s-drongo" />
                <add key="s-heyho" />
                <add key="s-bob"/>
                <add key="s-Black Adder" />
              </List2>
            
            </configuration>
            

            检索到字符串[]的代码

             private void button1_Click(object sender, EventArgs e)
                {
            
                    string[] output = CollectFromConfig("List1");
                    foreach (string key in output) label1.Text += key + Environment.NewLine;
                    label1.Text += Environment.NewLine;
                    output = CollectFromConfig("List2");
                    foreach (string key in output) label1.Text += key + Environment.NewLine;
                }
                private string[] CollectFromConfig(string key)
                {
                    NameValueCollection keyCollection = (NameValueCollection)ConfigurationManager.GetSection(key);
                    return keyCollection.AllKeys;
                }
            

            IMO,这很简单。随时证明我错了:)

            【讨论】:

              【解决方案9】:

              我使用键的命名约定,它就像一个魅力

              <?xml version="1.0" encoding="utf-8"?>
              <configuration>
                <configSections>
                  <section name="section1" type="System.Configuration.NameValueSectionHandler"/>
                </configSections>
                <section1>
                  <add key="keyname1" value="value1"/>
                  <add key="keyname21" value="value21"/>
                  <add key="keyname22" value="value22"/>
                </section1>
              </configuration>
              

              var section1 = ConfigurationManager.GetSection("section1") as NameValueCollection;
              for (int i = 0; i < section1.AllKeys.Length; i++)
              {
                  //if you define the key is unique then use == operator
                  if (section1.AllKeys[i] == "keyName1")
                  {
                      // process keyName1
                  }
              
                  // if you define the key as a list, starting with the same name, then use string StartWith function
                  if (section1.AllKeys[i].Startwith("keyName2"))
                  {
                      // AllKeys start with keyName2 will be processed here
                  }
              }
              

              【讨论】:

              • 有一个标准的检索并通过指定键和值是一个很好的选择
              • 我认为这是最干净的解决方案。它还允许可能已经包含许多常用分隔符的值。我实现了它并解决了我的问题,我不必担心有一天可能需要一个使用该特定分隔符的值。
              【解决方案10】:

              我发现解决方案非常简单。如果所有键都将具有相同的值,只需使用唯一值作为键并省略该值。

              <configSections>
                  <section name="appSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
                  <section name="filelist" type="System.Configuration.AppSettingsSection, System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" restartOnExternalChanges="false" requirePermission="false"/>
               </configSections>
              
              <filelist>
                  <add key="\\C$\Temp\File01.txt"></add>
                  <add key="\\C$\Temp\File02.txt"></add>
                  <add key="\\C$\Temp\File03.txt"></add>
                  <add key="\\C$\Temp\File04.txt"></add>
                  <add key="\\C$\Temp\File05.txt"></add>
                  <add key="\\C$\Temp\File06.txt"></add>
                  <add key="\\C$\Temp\File07.txt"></add>
                  <add key="\\C$\Temp\File08.txt"></add>
              </filelist>
              

              然后在代码中简单地使用以下内容:

              private static List<string> GetSection(string section)
                      {
                          NameValueCollection sectionValues = ConfigurationManager.GetSection(section) as NameValueCollection;
              
                          return sectionValues.AllKeys.ToList();
                      }
              

              结果是:

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2014-04-28
                相关资源
                最近更新 更多