2

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

私がこの問題に遭遇した最初の人だとは想像できません。何か案は?

4

3 に答える 3

3

明示的な「ねえ、ここに値のリストを詰め込みたい」というハンドラーはありませんが、いくつかのオプションがあります。

カスタムIConfigurationSectionHandler(要素コレクションなどよりもはるかに単純)を実装し、次を介して参照します。

<configSections>
    <sectionGroup name="mysection" type="type of handler"/>
</configSections>

<mysection>
  some xml representation of values
</mysection>

次のように、既存のハンドラーの 1 つにピギーバックしSingleTagSectionHandlerます。構成ファイル内のこのエントリから一連の値を抽出する毛むくじゃらに見える 1 つのライナーを次に示します。

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

または少し分割します。

var section = (Hashtable)ConfigurationManager.GetSection("TemperaturePoints");
var packedValues = (string)section["values"];
var unpackedValues = packedValues.Split(',');
var asDoubles = unpackedValues.Select(double.Parse).ToArray();
于 2013-03-04T18:16:31.360 に答える
3

あまりカスタマイズせずにこれを機能させることができました。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);

そして設定ファイル:

<DomainConfig DoubleArray="1.0,2.0,3.0"></DomainConfig>
于 2013-03-05T18:34:03.907 に答える
1

これは私にとって正しいと感じる実装です。

  • 各値を別々の行に (簡単に比較するため)
  • S/N 比が高いエンコーディングのオーバーヘッドを最小限に抑える
  • 値の簡単な読み取り

下部に限定的な説明があります。System.Configuration API の基本について詳しく知りたい場合は、CodeProject.comの Jon Rista のUnraveling the Mysteries of .NET 2.0 Configuration記事シリーズをお勧めします。

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>

API の使用

class Program
{
    static void Main(string[] args)
    {
        foreach (var s in StringCollectionConfigSection.Named("strings"))
        {
            Console.WriteLine(ignoreExpression);
        }
        foreach (var d in StringCollectionConfigSection.Named("strings"))
        {
            Console.WriteLine(ignoreExpression);
        }
    }
}

実装

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

コードに関する学習ポイント。

  • app.config では、config セクションの名前を定義するときに、名前空間とアセンブリ名を使用していることを確認してください。
  • コレクションに余分なサブ要素は必要ありませんでした。文字列値を保持する要素のみが必要でした。
    • クラスのプロパティでConfigurationPropertyAttribute定義されたは、空の名前を使用して、達成したいデフォルトのコレクション スタイルを実現します。StringElementCollection ElementsStringCollectionConfigSection

<strings>
    <elements>
       <add>...</add>
       <add>...</add>
    <elements>
</strings>
  • DeserializeElementonにより、属性のStringElement代わりに XmlNode の innerText を値として使用できます。

  • IEnumerator<string>onとonをConfigurationElementCollection組み合わせると、私が求めていたクリーンな API が得られます。StringElementCollection Named(string configSection)StringCollectionConfigSection

于 2015-11-23T18:00:27.173 に答える