Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带有基元类型的ConfigurationElementCollection_C#_App Config_System.configuration - Fatal编程技术网

C# 带有基元类型的ConfigurationElementCollection

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

我正在使用System.Configuration命名空间类型来存储应用程序的配置。我需要存储一组基本类型(System.Double)作为配置的一部分。创建以下内容似乎有些过分:

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

这是我觉得合适的实现

  • 单独一行上的每个值(便于区分)
  • 高信噪比编码的最小开销
  • 价值观的简单解读
底部提供了有限的解释。如果您想了解更多System.Configuration API的基础知识,我推荐Jon Rista在CodeProject.com上的文章系列

APP.CONFIG

<?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
    上的
    DeserializeElement
    允许我使用XmlNode的innerText作为值,而不是属性

  • ConfigurationElementCollection
    上的
    IEnumerator
    StringCollectionConfigSection上的
    StringElementCollection Named(string configSection)
    相结合,为我提供了所需的干净API

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>