2010-04-18 92 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以获取新值。