2010-04-18 93 views
4

我必須在應用程序設置中存儲複雜類型。我認爲將其存儲爲XML將最有效。有沒有辦法在應用程序設置中使用字典或xml?

問題是我不知道如何存儲XML。我更願意將其作爲託管XML存儲,而不是僅使用一串原始XML在每次訪問時解析它。我設法將該設置的Type列設置爲XDocument,但我無法設置其值。

有沒有辦法在應用程序設置中使用XDocument或XML?

更新

我找到了一種方法,只需編輯.settings與XML編輯器文件。

我將其更改爲custom serializable dictionary,但在嘗試訪問設置屬性(我將其設置爲默認值的序列化表示形式)時出現以下錯誤。

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

任何想法將不勝感激。

回答

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文件)爲全名(即MyProject.Rooms)。 然後,我使自己成爲一個樣本反序列化的示例,並將其複製到.settings編輯器中的值字段以具有默認值。它的效果很好。 它確實不是一本字典,但我仍然可以在房間類和內部字典中實現(即通過Room.Room返回節)。

任何好主意仍然很好,我仍然在尋找能夠在.settings文件中使用IDictinoary秒。

此外,我開了一個connection吧,請善待和投票!

2

我最終什麼事做,因爲這是阻力最小的路徑是使用內置在.NET Fx中的配置類儘管下面的代碼是用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"]; } 
    } 
} 

雖然其在*不正確的IDictionary的config文件就可以完成這項工作,如果你的配置文件在運行時更新,您不必重新啓動應用程序或回收AppPool以獲取新值。