【问题标题】:How to include simple collections in ConfigurationSection如何在 ConfigurationSection 中包含简单集合
【发布时间】:2011-02-11 13:05:48
【问题描述】:

有没有办法让我在我的 ConfigurationSection 的自定义子类中包含一个简单的字符串数组或 List? (或者简单数据对象的数组或通用列表?)

我正在熟悉新的(而且非常冗长的)ConfigurationSection、ConfigurationElement 和 ConfigurationElementCollection 类,但我还不是专家。

似乎 ConfigurationSection 应该自己处理简单的集合/列表,而无需我为每一个创建自定义 ConfigurationElementCollection 子类。但是我在网上没有找到任何关于这个能力的参考。

编辑:接受 Dan 的回复作为答案,因为这可能是我最接近“旧式”configSections 的内容。我总是发现任何 XmlSerializable 对象都可以轻松成为 configSection,这很容易、灵活且优雅。我确信新框架更强大;但是很遗憾,对于简单的配置结构来说太麻烦了,以至于我们不得不回到 String.Split()。

【问题讨论】:

    标签: .net configuration web-config app-config config


    【解决方案1】:

    这是一个简单的例子。

    //START CODE
    
    
    //MyCompany.MyProject.csproj which results in MyCompany.MyProject.dll
    //Add a Folder called "Configuration"
    
    namespace MyCompany.MyProject.Configuration
    {
        using System;
        using System.Collections.Generic;
        using System.Linq;
        using System.Text;
    
        using System.Configuration;
    
    
        public class TransformationToDirectoryMapping : ConfigurationElement
        {
    
            private const string FRIENDLY_NAME = "FriendlyName";
            private const string PICKUP_FOLDER = "PickupFolder";
    
            [ConfigurationProperty(FRIENDLY_NAME, DefaultValue = "", IsKey = false, IsRequired = true)]
            public string FriendlyName
            {
                get
                {
                    return ((string)(base[FRIENDLY_NAME]));
                }
                set
                {
                    base[FRIENDLY_NAME] = value;
                }
            }
    
            [ConfigurationProperty(PICKUP_FOLDER, DefaultValue = "", IsKey = true, IsRequired = true)]
            public string PickupFolder
            {
                get
                {
                    return ((string)(base[PICKUP_FOLDER]));
                }
                set
                {
                    base[PICKUP_FOLDER] = value;
                }
            }
    
    
    
        }
    
        //-----------------------------------------------------------------------
    
        //-----------------------------------------------------------------------
    
        [ConfigurationCollection(typeof(TransformationToDirectoryMapping))]
        public class TransformationToDirectoryMappingCollection : ConfigurationElementCollection
        {
    
            protected override ConfigurationElement CreateNewElement()
            {
                return new TransformationToDirectoryMapping();
            }
    
            protected override object GetElementKey(ConfigurationElement element)
            {
                return ((TransformationToDirectoryMapping)(element)).PickupFolder;
            }
    
    
            public TransformationToDirectoryMapping this[int idx]
            {
                get
                {
                    return (TransformationToDirectoryMapping)BaseGet(idx);
                }
            }
    
            new public TransformationToDirectoryMapping this[string key]
            {
                get
                {
                    return (TransformationToDirectoryMapping)BaseGet(key);
                }
            }
        }
    
        //-----------------------------------------------------------------------
    
        //-----------------------------------------------------------------------
    
        public class TransformationToDirectoryMappingConfigSection : ConfigurationSection
        {
            private const string TRANSFORMATION_TO_DIRECTORY_MAPPINGS = "TransformationToDirectoryMappings";
    
            [ConfigurationProperty(TRANSFORMATION_TO_DIRECTORY_MAPPINGS)]
            public TransformationToDirectoryMappingCollection TransformationToDirectoryMappingItems
            {
                get { return ((TransformationToDirectoryMappingCollection)(base[TRANSFORMATION_TO_DIRECTORY_MAPPINGS])); }
            }
        }
    
        //-----------------------------------------------------------------------
    
        //-----------------------------------------------------------------------
    
        public static class MyRetriever
        {
            public const string MAPPINGS_CONFIGURATION_SECTION_NAME = "TransformationToDirectoryMappingsSection";
    
            public static TransformationToDirectoryMappingCollection GetTheCollection()
            {
                TransformationToDirectoryMappingConfigSection mappingsSection = (TransformationToDirectoryMappingConfigSection)ConfigurationManager.GetSection(MAPPINGS_CONFIGURATION_SECTION_NAME);
                if (mappingsSection != null)
                {
                    return mappingsSection.TransformationToDirectoryMappingItems;
                }
                return null; // OOPS!
    
            }
        }
    
    }
    

    //配置文件的XML:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
      <configSections>
        <section name="TransformationToDirectoryMappingsSection" type="MyCompany.MyProject.Configuration.TransformationToDirectoryMappingConfigSection, MyCompany.MyProject"/>
      </configSections>
    
      <TransformationToDirectoryMappingsSection>
        <TransformationToDirectoryMappings>
          <add FriendlyName="Hello" PickupFolder="C:\WUWUTemp\pickups\pickup11\" />
          <add FriendlyName="GoodBye" PickupFolder="C:\WUWUTemp\pickups\pickup12\" />
        </TransformationToDirectoryMappings>
      </TransformationToDirectoryMappingsSection>
    </configuration>
    

    【讨论】:

    • 感谢您的回复——尤其是对一个相对较老的问题。 :) 不幸的是,这仍然不是我想要的。您有一个第一类对象数组,每个对象都包含几个字符串。我想要的只是一个字符串数组。使用“旧式”配置部分,我能够在不创建自定义对象的情况下做到这一点。我希望有一种方法可以在新的配置框架中做到这一点,而无需创建一个对象来实质上包装一个 List.
    • 我用过。为我节省了大量时间。一项调整:公共静态只读字符串 MAPPINGS_CONFIGURATION_SECTION_NAME = "TransformationToDirectoryMappingsSection";应该是 public const string MAPPINGS_CONFIGURATION_SECTION_NAME = "TransformationToDirectoryMappingsSection";
    • 鹰眼细节奖授予 __JDN____!哈哈,你给我了。我改变了它。很高兴它有帮助。
    【解决方案2】:

    应用设置架构

    http://msdn.microsoft.com/en-us/library/8eyb2ct1.aspx

    好吧,一个老帖子,但是当我遇到类似情况时我记得它:

    ...

    如果您转到项目/项目属性(在 VS2008 或 VS2010 中)。 有一个“设置”选项卡。

    如果你添加一个新值......

    其中一种类型被称为: System.Collections.Specialized.StringCollection

    给它起个名字(我用的是“FavoriteColors”)。

    设置类型(如上所示)。

    设置值。

    “字符串集合编辑器”显示“在集合中输入字符串(每行一个)”。

    我输入了:

    红色

    黄色

    黑色

    白色

    这会将一些 xml 添加到您的 app.config 文件中。

        <setting name="FavoriteColors" serializeAs="Xml">
            <value>
                <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                    <string>red</string>
                    <string>yellow</string>
                    <string>black</string>
                    <string>white</string>
                </ArrayOfString>
            </value>
        </setting>
    

    (您最好完成这些步骤,而不是粘贴上面的 xml,因为(为简洁起见)我没有将所有 xml 添加到生成的这篇文章中。

    您应该能够通过如下代码“获取”这些值:

    private void ShowMyFavoriteColors()
    {
                Properties.Settings.Default.FavoriteColors.Cast<string>().ToList().ForEach(myfavcolor =>
                {
                    string temp = myfavcolor;
                });
    }
    

    请注意,上述步骤将生成以下 C# 代码(为您创建的自动代码......这是您创建的不是代码) 但代码如下所示:

            [global::System.Configuration.ApplicationScopedSettingAttribute()]
            [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
            [global::System.Configuration.DefaultSettingValueAttribute(@"<?xml version=""1.0"" encoding=""utf-16""?>
    <ArrayOfString xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
      <string>red</string>
      <string>yellow</string>
      <string>black</string>
      <string>white</string>
    </ArrayOfString>")]
            public global::System.Collections.Specialized.StringCollection FavoriteColors {
                get {
                    return ((global::System.Collections.Specialized.StringCollection)(this["FavoriteColors"]));
                }
            }
        }
    }
    

    【讨论】:

    • 感谢您的回复 - 这确实是一个旧帖子!我实际上不再参与激发它的项目。 :) 在我写这个问题的时候,我知道你在这里概述的技术,所以我没有使用它一定有一些原因。但对于我的一生,我不记得为什么。当我有机会时,我会更多地使用它,或者将你的帖子标记为答案,或者提供更多信息来说明它为什么不适合我的需求。再次感谢!
    • 糟糕——我刚刚意识到我已经标记了一个答案,我不想撤销它。但我肯定会赞成你的回应。 :)
    【解决方案3】:

    好的,你要求的很简单。嗯,存储一系列字符串的最简单方法是使用分隔列表(例如,逗号分隔)。这样你就可以将它存储在一个元素中(比如在 appSettings 中)。

    <add key="weekDays" value="Monday,Tuesday,Wednesday,Thursday,Friday"/>
    

    当然,这有缺点,但在大多数情况下,对于简单的列表来说效果很好。然后您可以使用String.Split() 将其转换回数组/列表。

    否则,您将返回 ConfigurationSection 元素,我同意,使用这些元素非常冗长且笨拙。但我不知道有什么其他方法,恐怕(但很高兴被证明是错误的!)。

    【讨论】:

    • Dan D - 谢谢,但你是对的,我不是在寻找那么简单的东西! :) 我以前使用过分隔列表和 String.Split,我相信我会再次使用它。但我希望有一些更优雅的东西。也许其他人会回复我们错过的内容。
    • 我不这么认为,但有时开发人员会忽略显而易见的事情。这是我们的天性!
    【解决方案4】:

    我知道这个问题很久以前就已经回答了......但是在我的“ConfigurationElement”类中,对于字符串收集,我通常会执行以下操作:

    [ConfigurationProperty("myStringCollectionProperty", DefaultValue = "")]
    [TypeConverter(typeof(CommaDelimitedStringCollectionConverter))]
    public StringCollection MyStringCollectionProperty
    {
        get { return (StringCollection)this["myStringCollectionProperty"]; }
        set { this["myStringCollectionProperty"] = value; }
     }
    

    您可以使用

    从此属性中获取字符串列表
    List<string> myStrings = config.MyStringCollectionProperty.Cast<string>.ToList()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-23
      • 1970-01-01
      • 2023-03-19
      相关资源
      最近更新 更多