How to include simple collections in Configuration

2019-01-27 13:29发布

Is there a way for me to include a simple array of strings, or List<string> on my custom subclass of ConfigurationSection? (Or an array or generic list of simple data objects, for that matter?)

I'm becoming familiar with the new (and VERY verbose) ConfigurationSection, ConfigurationElement, and ConfigurationElementCollection classes, but I'm by no means an expert yet.

It seems like ConfigurationSection should handle simple collections/lists on its own, without me having to create a custom ConfigurationElementCollection subclass for each and every one. But I haven't found any reference to this ability online.

Edit: accepting Dan's response as the answer, since it's probably the closest thing I'm going to get to the "old style" configSections. I always found it easy, flexible, and elegant that any XmlSerializable object could easily become a configSection. I'm sure the new framework is more powerful; however it's sad that it is SO cumbersome for simple configuration contructs, that we're reduced to going back to String.Split().

4条回答
太酷不给撩
2楼-- · 2019-01-27 14:21

Here's a simple example.

//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 for config file:

<?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>
查看更多
狗以群分
3楼-- · 2019-01-27 14:25

Application Settings Architecture

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

Ok, an old post, but I remembered it when I came across a similar situation:

...

If you go to Project / Project Properties (in VS2008 or VS2010). There is a "Settings" tab.

If you add a new value....

One of the types is called: System.Collections.Specialized.StringCollection

Give it a name (I used "FavoriteColors").

Set the type (as instructed above).

Set the value(s).

The "String Collection Editor" says "Enter the strings in the collection (one per line)".

I entered:

Red

Yellow

Black

White

This will add some xml to your app.config file.

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

(You'll be better off going through the steps rather than pasting the xml above, because (for conciseness) I did not add all the xml to this post that is generated.

You should be able to "get at" the values via code like this:

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

Note, the steps above will produce the below C# code (auto code created for you.... it is not code you create) but the code looks like this:

        [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"]));
            }
        }
    }
}
查看更多
我只想做你的唯一
4楼-- · 2019-01-27 14:27

I know that the question has been answered long time ago... but in my 'ConfigurationElement' classes, for string collection, I usually do the following:

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

And you can get a string list from this property with

List<string> myStrings = config.MyStringCollectionProperty.Cast<string>.ToList()
查看更多
不美不萌又怎样
5楼-- · 2019-01-27 14:31

OK, you asked for simple. Well, the simplest way to store a series of strings would be to use a delimited list (say, comma separated). That way you can store it in just one element (say in appSettings).

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

Of course, this has drawbacks but in most cases works well for a simple list. You can then use String.Split() to convert it back to an array/list.

Otherwise you are back to ConfigurationSection elements which, I agree, are very verbose and clumsy to work with. But I don't know of any other way, I'm afraid (but am happy to be proved wrong!).

查看更多
登录 后发表回答