How to include simple collections in ConfigurationSection
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 i开发者_JAVA百科s SO cumbersome for simple configuration contructs, that we're reduced to going back to String.Split().
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>
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"]));
}
}
}
}
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!).
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()
精彩评论