2008年11月27日 星期四

[Visual Studio]在Properties.Settings裡面使用Hashtable或Dictionary的方法

其實這算是一種折衷的方法,並不是真的建立Hashtable/Dictionary在Properties裡面。

我自己試過的結果,在Properties.Settings.Default裡面雖然可以建立Hashtable(沒法建立Dictionary),但是在程式裡面去讀取這個Hashtable會出現Exception,因為這個型別並沒有被初始化及讀取user.config的值,不像其他Properties.Settings.Default其他型別的值都會自動被建立並初始化讀取user.config的值,所以沒法使用。(至少我不知道如何用)

最後在網路查到使用的方法,就是先將Hashtable/Dictionary的值序列化成XML字串,再用string型別把值塞到Properties.Settings.Default裡面。

讀取出來也是一樣,先讀出string的值,將string反序列化,將值寫回指定的Hashtable/Dictionary。

下面是Source Code參考:

using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Xml.Serialization;

namespace Neil.Tools
{
    public class XMLSerializing
    {
        //這邊可以改寫為擴充方法
        /// <summary>
        /// 將Dictionary轉為字串。
        /// </summary>
        /// <typeparam name="T1">Key型別,通常為string</typeparam>
        /// <typeparam name="T2">Value型別,通常為string</typeparam>
        /// <param name="d">來源Dictionary</param>
        /// <returns>傳回轉換後字串</returns>
        public static string ToDictionaryString<T1,T2>(Dictionary<T1, T2> d)
        {
            if (d.Count == 0)
            return "";
            
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            Serialize(sw, d);
            return sb.ToString();
        }


        //這邊可以改寫為擴充方法
        /// <summary>
        /// 將string轉回Dictionary
        /// </summary>
        /// <typeparam name="T1">Key型別,通常為string</typeparam>
        /// <typeparam name="T2">Value型別,通常為string</typeparam>
        /// <param name="value">XML格式的文字字串</param>
        /// <returns>傳回Dictionary<T1,T2></returns>
        public static Dictionary<T1, T2> ToDictionary<T1,T2>(string value)
        {
            Dictionary<T1, T2> d  = null;
            try
            {
                d = new Dictionary<T1, T2>();
                StringReader sr = new StringReader(value);
                Deserialize(sr, d);

                if (d.Count == 0)
                    return null;
            }
            catch
            { }

            return d;
        }

        public static void Serialize(TextWriter writer, IDictionary dictionary)
        {
            List<Entry> entries = new List<Entry>(dictionary.Count);
            foreach (object key in dictionary.Keys)
            {
                entries.Add(new Entry(key, dictionary[key]));
            }

            XmlSerializer serializer = new XmlSerializer(typeof(List<Entry>));
            serializer.Serialize(writer, entries);
        }

        public static void Deserialize(TextReader reader, IDictionary dictionary)
        {
            dictionary.Clear();
            XmlSerializer serializer = new XmlSerializer(typeof(List<Entry>));
            List<Entry> list = (List<Entry>)serializer.Deserialize(reader);

            foreach (Entry entry in list)
            {
                dictionary[entry.Key] = entry.Value;
            }
        }

        public class Entry
        {
            public object Key;
            public object Value;

            public Entry()
            {
            }

            public Entry(object key, object value)
            {
                Key = key;
                Value = value;
            }
        }
    }
}

而轉換為XML字串的Dictionary會像下面這種內容存儲在user.config:

<setting name="ListViewColumnsOrder" serializeAs="String">
                <value>&lt;?xml version="1.0" encoding="utf-16"?&gt;
&lt;ArrayOfEntry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"&gt;
  &lt;Entry&gt;
    &lt;Key xsi:type="xsd:string"&gt;lvQueryPatient&lt;/Key&gt;
    &lt;Value xsi:type="xsd:string"&gt;0,1,2,3,4&lt;/Value&gt;
  &lt;/Entry&gt;
  &lt;Entry&gt;
    &lt;Key xsi:type="xsd:string"&gt;lvQueryStudy&lt;/Key&gt;
    &lt;Value xsi:type="xsd:string"&gt;0,1,2,5,3,4&lt;/Value&gt;
  &lt;/Entry&gt;
&lt;/ArrayOfEntry&gt;</value>
            </setting>

 

延伸閱讀: XML Serializing a Hashtable or generic Dictionary

延伸閱讀: Storing a hashtable in the .config file?

沒有留言:

張貼留言