C# 带有基元类型的ConfigurationElementCollection
我正在使用System.Configuration命名空间类型来存储应用程序的配置。我需要存储一组基本类型(System.Double)作为配置的一部分。创建以下内容似乎有些过分:C# 带有基元类型的ConfigurationElementCollection,c#,app-config,system.configuration,C#,App Config,System.configuration,我正在使用System.Configuration命名空间类型来存储应用程序的配置。我需要存储一组基本类型(System.Double)作为配置的一部分。创建以下内容似乎有些过分: [ConfigurationCollection(typeof(double), AddItemName="TemperaturePoint", CollectionType=ConfigurationElementCollectionType.BasicMap)] class DoubleCollecti
[ConfigurationCollection(typeof(double), AddItemName="TemperaturePoint",
CollectionType=ConfigurationElementCollectionType.BasicMap)]
class DoubleCollection : ConfigurationElementCollection
{
protected override ConfigurationElement CreateNewElement()
{
return // Do I need to create a custom ConfigurationElement that wraps a double?
}
protected override object GetElementKey(ConfigurationElement element)
{
return // Also not sure what to do here
}
}
我无法想象我是第一个遇到这个问题的人。有什么想法吗?没有明确的“嘿,我想在这里填充一个值列表”处理程序,但您有几个选项:
通过以下方式实现自定义IConfigurationSectionHandler
(比元素集合等更简单)和引用:
<configSections>
<sectionGroup name="mysection" type="type of handler"/>
</configSections>
<mysection>
some xml representation of values
</mysection>
或者分开一点:
var section = (Hashtable)ConfigurationManager.GetSection("TemperaturePoints");
var packedValues = (string)section["values"];
var unpackedValues = packedValues.Split(',');
var asDoubles = unpackedValues.Select(double.Parse).ToArray();
我能够让这个工作没有太多的定制。这与JerKimball的答案类似,但我通过使用ConfigurationProperty的TypeConverter属性来避免处理自定义字符串处理 我的自定义配置节实现:
using System.Configuration;
using System.ComponentModel;
class DomainConfig : ConfigurationSection
{
[ConfigurationProperty("DoubleArray")]
[TypeConverter(typeof(CommaDelimitedStringCollectionConverter))]
public CommaDelimitedStringCollection DoubleArray
{
get { return (CommaDelimitedStringCollection)base["DoubleArray"]; }
}
}
如何使用:
var doubleValues = from string item in configSection.DoubleArray select double.Parse(item);
和配置文件:
<configuration>
<configSections>
<section name="TemperaturePoints"
type="System.Configuration.SingleTagSectionHandler"
allowLocation="true"
allowDefinition="Everywhere"/>
</configSections>
<TemperaturePoints values="1,2,3,4,5,6,7,8,9,10"/>
</configuration>
var values = ((string)((Hashtable)ConfigurationManager
.GetSection("TemperaturePoints"))["values"])
.Split(',')
.Select(double.Parse);
<DomainConfig DoubleArray="1.0,2.0,3.0"></DomainConfig>
这是我觉得合适的实现
- 单独一行上的每个值(便于区分)
- 高信噪比编码的最小开销
- 价值观的简单解读
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="strings"
type="Sample.StringCollectionConfigSection, SampleAssembly"/>
<section name="databases"
type="Sample.StringCollectionConfigSection, SampleAssembly"/>
</configSections>
<strings>
<add>dbo.Foo</add>
<add>dbo.Bar</add>
</strings>
<databases>
<add>Development</add>
<add>Test</add>
<add>Staging</add>
</databases>
</configuration>
实施
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
hnamespace Sample
{
public sealed class StringCollectionConfigSection : ConfigurationSection
{
public static StringElementCollection Named(string configSection)
{
var section = (StringCollectionConfigSection)ConfigurationManager.GetSection(configSection);
return section.Elements;
}
[ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public StringElementCollection Elements
{
get { return (StringElementCollection)base[""]; }
set { base[""] = value; }
}
}
[ConfigurationCollection(typeof(StringElement))]
public sealed class StringElementCollection : ConfigurationElementCollection, IEnumerable<string>
{
public StringElement this[int index]
{
get { return (StringElement)BaseGet(index); }
set
{
if (BaseGet(index) != null) { BaseRemoveAt(index); }
BaseAdd(index, value);
}
}
public new StringElement this[string key]
{
get { return (StringElement)BaseGet(key); }
}
protected override ConfigurationElement CreateNewElement()
{
return new StringElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((StringElement)element).Value;
}
public new IEnumerator<string> GetEnumerator()
{
var enumerator = base.GetEnumerator();
while (enumerator.MoveNext())
{
yield return ((StringElement)enumerator.Current).Value;
}
}
}
public class StringElement : ConfigurationElement
{
protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
{
Value = (string)reader.ReadElementContentAs(typeof(string), null);
}
public string Value {get; private set; }
}
}
上的StringElement
允许我使用XmlNode的innerText作为值,而不是属性DeserializeElement
上的ConfigurationElementCollection
与IEnumerator
StringCollectionConfigSection上的
相结合,为我提供了所需的干净APIStringElementCollection Named(string configSection)
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Xml;
hnamespace Sample
{
public sealed class StringCollectionConfigSection : ConfigurationSection
{
public static StringElementCollection Named(string configSection)
{
var section = (StringCollectionConfigSection)ConfigurationManager.GetSection(configSection);
return section.Elements;
}
[ConfigurationProperty("", Options = ConfigurationPropertyOptions.IsDefaultCollection)]
public StringElementCollection Elements
{
get { return (StringElementCollection)base[""]; }
set { base[""] = value; }
}
}
[ConfigurationCollection(typeof(StringElement))]
public sealed class StringElementCollection : ConfigurationElementCollection, IEnumerable<string>
{
public StringElement this[int index]
{
get { return (StringElement)BaseGet(index); }
set
{
if (BaseGet(index) != null) { BaseRemoveAt(index); }
BaseAdd(index, value);
}
}
public new StringElement this[string key]
{
get { return (StringElement)BaseGet(key); }
}
protected override ConfigurationElement CreateNewElement()
{
return new StringElement();
}
protected override object GetElementKey(ConfigurationElement element)
{
return ((StringElement)element).Value;
}
public new IEnumerator<string> GetEnumerator()
{
var enumerator = base.GetEnumerator();
while (enumerator.MoveNext())
{
yield return ((StringElement)enumerator.Current).Value;
}
}
}
public class StringElement : ConfigurationElement
{
protected override void DeserializeElement(XmlReader reader, bool serializeCollectionKey)
{
Value = (string)reader.ReadElementContentAs(typeof(string), null);
}
public string Value {get; private set; }
}
}
<strings>
<elements>
<add>...</add>
<add>...</add>
<elements>
</strings>