2010-04-18 4 views
4

응용 프로그램 설정에 복잡한 유형을 저장해야합니다. XML로 저장하는 것이 가장 효과적 일 것이라고 생각했습니다.응용 프로그램 설정에서 사전 또는 xml을 사용할 수 있습니까?

문제는 XML 저장 방법을 모르겠다는 것입니다. 필자는 각 액세스에서 파싱해야하는 원시 XML 문자열을 사용하는 대신 관리되는 XML로 저장하는 것을 선호합니다. XDocument 설정의 Type 열을 설정할 수 있었지만 그 값을 설정할 수 없었습니다.

응용 프로그램 설정에서 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

은 다음과 같습니다

나는 내 값의 간단한 직렬화 클래스를 만든 다음 .settings 파일에서 다음

<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 

를, 나는 설정의 유형 (xml 편집기로 열리는 .setting 파일)을 Rooms의 전체 이름 (예 : MyProject.Rooms)으로 편집했습니다. 그런 다음 샘플을 deserialize 한 샘플을 만들고 .settings 편집기의 값 필드에 복사하여 기본값을 갖습니다. 그것은 위대한 작품. 실제로는 사전이 아니지만 Rooms 클래스 및 내부 사전 (여전히 Room.Room을 반환하는 섹션)을 구현할 수 있습니다.

좋은 아이디어가 있다면 언제나 환영받을 수 있습니다. .settings 파일에 IDictinoary의를 사용할 수 있습니다.

을 게다가, 그것을 위해 connection을 열어, 친절하고 투표하십시오! 나는이 최소 저항의 경로 때문에 일을 결국 무엇

2

내장을 사용했다 - in .NET Fx의 구성 클래스. 아래 코드가 C# 인 경우에도 거의 어려움없이 VB.NET으로 변환 할 수 있어야합니다 (또는 편집 및 컴파일 프로젝트에서 참조 할 수있는 어셈블리로 가져옵니다).

약간의 어려움없이 ConfigurationElementCollection 클래스를 키/값 쌍 사전으로 변환 할 수 있습니다 (값 쌍에 반사를 사용해야하거나 값 쌍으로 저장할 클래스가 설정 클래스를 가질 수 있음) ConfigurationElement에서 생성자 인수로 상속).

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

을 그리고 구성 클래스에 의해 표현 :

// 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(); 
    } 
} 

그리고 여기가 내가 우리의 시스템에서 우리의 샤딩 전략 위의 기본 클래스 코드를 사용하는 예입니다 (이름은 무고한을 보호하기 위해 변경) 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"]; } 
    } 
} 

A *에서 그 사실이 아니다 IDictionary가이 작업을 처리 할 수 ​​있으며, 구성 파일은 실행시 업데이트되는 경우가없는 파일의 .config 동안 응용 프로그램을 다시 시작하거나 AppPool을 재사용하여 새 값을 가져옵니다.

관련 문제