簡體   English   中英

使用字典將xml反序列化為對象

[英]Deserializing xml to object with dictionary

這是我的課程結構:

class DataItem
{
   public string Id { get; set; }
   public string Type { get; set; }

   private Dictionary<string, DataProperty> properties = new Dictionary<string, DataProperty>();

   public Dictionary<string, DataProperty> Properties
   {
       get { return properties; }
       set { properties = value; }
   }
}

public class DataProperty
{    
      public string Key { get; set; }
      public string Value { get; set; }
      public bool Required { get; set; }
}

這是我要使用的XML( 注:如果需要,我可以更改xml ):

<Data>
  <DataItem>
    <id>ph15</id>
    <type>core</type>
    <properties>
      <DataProperty>
        <key>size</key>
        <value>50%</value>
        <required>false</required>
      </DataProperty>
      <DataProperty>
        <key>color</key>
        <value>red</value>
        <required>true</required>
      </DataProperty>
    </properties>
  </DataItem>
  <DataItem>
    <id>ph234</id>
    <type>core</type>
    <properties>
    </properties>
  </DataItem>
</Data>

最終,XML應該加載到另一個字典中:

private Dictionary<string, DataItem> Mydata;

不幸的是,通用詞典無法xml序列化。

解決方法是創建一個單獨的字段,專門用於支持序列化,該序列化將字典的元素公開為鍵/值對的列表。 然后,您還必須使用XmlIgnore屬性標記字典成員。

另外,您可以使用XmlSerializer之外的其他東西(例如DataContractSerializer )來支持字典類型。

這里是文章鏈接 ,提供了一個很好的示例,說明了如何修改類型以支持帶字典的XML序列化。

如果使用此代碼,則有一點很重要-序列化的項目可能會以任意順序出現在輸出中。 這是因為使用專斷詞(無序)作為數據的存儲模型的結果。

[XmlIgnore()]   
public Dictionary<string, DataProperty> Properties
{   
    set { properties = value; }   
    get { return properties ; }   
}


[XmlArray("Stuff")]   
[XmlArrayItem("StuffLine", Type=typeof(DictionaryEntry))]   
public DictionaryEntry[] PropertiesList
{   
    get  
    {   
        //Make an array of DictionaryEntries to return   
        DictionaryEntry[] ret=new DictionaryEntry[Properties.Count];   
        int i=0;   
        DictionaryEntry de;   
        //Iterate through Stuff to load items into the array.   
        foreach (KeyValuePair<string, DataProperty> props in Properties)   
        {   
            de = new DictionaryEntry();   
            de.Key = props.Key;   
            de.Value = props.Value;   
            ret[i]=de;   
            i++;   
        }   
        return ret;   
    }   
    set  
    {   
        Properties.Clear();   
        for (int i=0; i<value.Length; i++)   
        {   
            Properties.Add((string)value[i].Key, (DataProperty)value[i].Value);   
        }   
    }   
}  

我知道以前已經回答過這個問題,但是由於我有一種非常簡潔的方式(代碼)來使用DataContractSerializer類(由WCF使用,但是可以並且應該在任何地方使用)進行IDictionary序列化,所以我不能拒絕在這里提供它:

public static class SerializationExtensions
{
    public static string Serialize<T>(this T obj)
    {
        var serializer = new DataContractSerializer(obj.GetType());
        using (var writer = new StringWriter())
        using (var stm = new XmlTextWriter(writer))
        {
            serializer.WriteObject(stm, obj);
            return writer.ToString();
        }
    }
    public static T Deserialize<T>(this string serialized)
    {
        var serializer = new DataContractSerializer(typeof(T));
        using (var reader = new StringReader(serialized))
        using (var stm = new XmlTextReader(reader))
        {
            return (T)serializer.ReadObject(stm);
        }
    }
}

盡管我尚未對其進行測試,但它在.NET 4中可以完美運行,並且在.NET 3.5中也可以運行。 我將流式傳輸到字符串是因為它對我來說更方便,盡管我可以將較低級別的序列化引入Stream,然后用它來序列化為字符串,但是我傾向於只在需要時進行泛化(就像過早的優化是邪惡的一樣) ,這是過早的概括...)

用法很簡單:

// dictionary to serialize to string
Dictionary<string, object> myDict = new Dictionary<string, object>();
// add items to the dictionary...
myDict.Add(...);
// serialization is straight-forward
string serialized = myDict.Serialize();
...
// deserialization is just as simple
Dictionary<string, object> myDictCopy = 
    serialized.Deserialize<Dictionary<string,object>>();

myDictCopy將是myDict的逐字記錄副本。

您還將注意到,提供的通用方法將能夠序列化任何類型(據我所知),因為它不僅限於IDictionary接口,它實際上可以是任何通用類型T。

希望它可以幫助某個人!

我建議您使用DataContractSerializer。 它確實支持字典。

但是,另一種方法是創建一個具有Value和Key屬性的簡單對象。 然后使用List(Of thatObject),它應該可以工作。 但這取決於您是否只想傳輸值鍵數據,導致字典中一部分的所有其他方法均不可用。

簡短的答案: 你不能

這是因為即使您可以想象序列化方案,.NET序列化程序也不能保證重新序列化的鍵將具有相同的哈希值。

長答案: 可以,但這需要很多工作

為您提供的解決方案是對整個對象進行手動序列化,或用一個簡單的Wrapper屬性(將IDictionary包裹起來,但將其公開為成對列表)替換Dictionary。 (您可以稍后將其轉換。)

但是 :與上面的問題相同,您不能保證重新序列化的密鑰將具有與序列化之前相同的哈希碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM