4

アプリケーション設定に複合型を保存する必要があります。XMLとして保存するのが一番いいと思いました。

問題は、XMLを保存する方法がわからないことです。アクセスごとに解析する必要のある生のXMLの文字列だけを使用するのではなく、マネージドXMLとして保存することを好みます。設定のType列をXDocumentに設定できましたが、値を設定できませんでした。

アプリケーション設定でXDocumentまたはXMLを使用する方法はありますか?

アップデート

xmlエディターで.settingsファイルを編集するだけで方法を見つけました。

カスタムのシリアル化可能な辞書に変更しましたが、setting-propertyにアクセスしようとすると次のエラーが発生します(デフォルト値のシリアル化された表現に設定しました)。

The property 'Setting' could not be created from it's default value.
Error message: There is an error in XML document (1, 41).

任意のアイデアをいただければ幸いです。

4

2 に答える 2

2

私がしたこと(私はそれほど好きではありませんが、うまくいきます)は次のとおりです。

値の単純なシリアル化可能なクラスを作成しました。

<Xml.Serialization.XmlRoot("Rooms")> _
Public Class Rooms : Inherits List(Of Room)
End Class

<Serializable()> _
Public Class Room
    Private m_Room As String
    Public Property Room() As String
        Get
            Return m_Room
        End Get
        Set(ByVal value As String)
            m_Room = value
        End Set
    End Property

    Private m_Sections As New List(Of Section)
    Public ReadOnly Property Sections() As List(Of Section)
        Get
            Return m_Sections
        End Get
    End Property
End Class

<Serializable()> _
Public Class Section
    Private m_Section As String
    Public Property Section() As String
        Get
            Return m_Section
        End Get
        Set(ByVal value As String)
            m_Section = value
        End Set
    End Property
End Class

次に、.settingsファイルで、設定の種類(xmlエディターで開いた.settingファイル)をRoomsのフルネーム(つまり、MyProject.Rooms)に編集しました。次に、自分でサンプルの逆シリアル化されたサンプルを作成し、それを.settingsエディターのvalueフィールドにコピーして、デフォルト値を設定しました。それは素晴らしい働きをします。これは確かに辞書ではありませんが、Roomsクラスと内部辞書(Room.RoomごとにSectionsを返す)に実装することはできます。

IDictinoary良いアイデアはまだ歓迎されています。私はまだ.settingsファイルでsを使用できる方法を探しています。

その上、私はそれのために接続を開きました、親切にして投票してください!

于 2010-04-19T23:30:29.700 に答える
2

これが最も抵抗の少ないパスだったので、私がやったことは、.NETFxの組み込みのConfigurationクラスを使用することでした。以下のコードはC#ですが、ほとんど問題なくVB.NETに変換できます(または、プロジェクトから参照できるアセンブリに編集してコンパイルできます)。

ConfigurationElementCollectionクラスは、ほとんど問題なくキーと値のペアのディクショナリに変換できることに注意してください(値のペアにリフレクションを使用する必要がある場合や、値のペアがConfigurationElementから継承する設定クラスを取得する可能性があるため、格納するクラスを使用する必要がある場合があります)コンストラクター引数として)。

// ConfigurationElement.cs
public class ConfigurationElement : System.Configuration.ConfigurationElement
{
    protected T GetValue<T>(string key, T defaultValue)
    {
        var value = default(T);
        if (base[key] != null)
        {
            var str = base[key].ToString();
            try
            {
                if (!String.IsNullOrEmpty(str))
                    value = (T)Convert.ChangeType(str, typeof(T));
            }
            catch // use the default
            {
            }
        }

        return value;
    }
}

// ConfigurationElementCollection.cs
public abstract class ConfigurationElementCollection<TElement,TKey> : 
    ConfigurationElementCollection, 
    IEnumerable<TElement> where TElement : System.Configuration.ConfigurationElement, new()
{
    public TElement this[int index]
    {
        get { return (TElement)BaseGet(index); }
    }

    public TElement this[TKey key]
    {
        get { return (TElement)BaseGet(key); }
    }

    protected override System.Configuration.ConfigurationElement CreateNewElement()
    {
        return new TElement();
    }

    protected override object GetElementKey(System.Configuration.ConfigurationElement element)
    {
        return GetElementKey((TElement)element);
    }
    protected abstract TKey GetElementKey(TElement element);

    public TKey[] GetAllKeys()
    {
        var keys = BaseGetAllKeys();
        var ret = new TKey[keys.Length];
        for (var i = 0; i < keys.Length; i++)
            ret[i] = (TKey)keys[i];

        // done
        return ret; 
    }
    public void Add(TElement element)
    {
        BaseAdd(element);
    }
    public void Remove(TElement element)
    {
        BaseRemove(element);
    }
    public void Clear()
    {
        BaseClear();
    }

    IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator()
    {
        foreach (TElement element in this)
        {
            yield return element;
        }
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        throw new System.NotImplementedException();
    }
}

そして、これが私たちのシステムのシャーディング戦略に上記の基本クラスコードを使用する例です(無実を保護するために名前が変更されています):

<!-- web.config -->
<!-- ... -->
<configuration>
    <configSections>
        <section name="sharding" type="Domain.ShardingSection, Domain.Configuration" />
    </configSections>
</configuration>
<!-- ... -->
<sharding>
    <configurationMappings>
        <add lastDigit="0" sqlMapFileName="Shard-0.SqlMap.config" />
        <add lastDigit="1" sqlMapFileName="Shard-1.SqlMap.config" />
        <add lastDigit="2" sqlMapFileName="Shard-2.SqlMap.config" />
        <add lastDigit="3" sqlMapFileName="Shard-3.SqlMap.config" />
        <add lastDigit="4" sqlMapFileName="Shard-4.SqlMap.config" />
        <add lastDigit="5" sqlMapFileName="Shard-5.SqlMap.config" />
        <add lastDigit="6" sqlMapFileName="Shard-6.SqlMap.config" />
        <add lastDigit="7" sqlMapFileName="Shard-7.SqlMap.config" />
        <add lastDigit="8" sqlMapFileName="Shard-8.SqlMap.config" />
        <add lastDigit="9" sqlMapFileName="Shard-9.SqlMap.config" />
    </configurationMappings>
</sharding>

次に、上記のXMLインスタンスで表される構成クラス:

// ShardElement.cs
public class ShardElement : ConfigurationElement
{
    [ConfigurationProperty("lastDigit", IsKey=true, IsRequired=true)]
    public int LastDigit
    {
        get { return (int)this["lastDigit"]; }
    }

    [ConfigurationProperty("sqlMapFileName", IsRequired=true)]
    public string SqlMapFileName
    {
        get { return (string)this["sqlMapFileName"]; }
    }
}

// ShardElementCollection.cs
public class ShardElementCollection : ConfigurationElementCollection<ShardElement, int>
{
    protected override int GetElementKey(ShardElement element)
    {
        return element.LastDigit;
    }
}

 // ShardingSection.cs
 public class ShardingSection : ConfigurationSection
{
    public const string Name = "sharding";

    [ConfigurationProperty("configurationMappings")]
    public ShardingElementCollection ConfigurationMappings
    {
        get { return (ShardingElementCollection)base["configurationMappings"]; }
    }
}

* .configファイルでは真のIDictionaryではありませんが、ジョブを処理できます。実行時に構成ファイルが更新された場合、新しい値を取得するためにアプリケーションを再起動したり、AppPoolをリサイクルしたりする必要はありません。

于 2010-04-20T00:46:06.073 に答える