2011-10-01 46 views
6

我正在使用DataContractSerializer來序列化包含Dictionary<string,object>成員的對象,該成員標記爲[DataMember()]。這個想法是有一個靈活的對象屬性包,我不知道這些屬性可能是什麼。DataContractSerializer和Dictionary <string,object>在讀取時失敗

這時候我把intdoublestring對象到詞典中的偉大工程,但是當我在裏面放了List<string>未能與反序列化對象:

System.InvalidOperationException: Node type Element is not supported in this operation. 

整個字典是序列化到XML,它看起來相當合理:

<Attributes xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays"> 
    <d2p1:KeyValueOfstringanyType> 
     <d2p1:Key>name</d2p1:Key> 
     <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:string">Test object</d2p1:Value> 
    </d2p1:KeyValueOfstringanyType> 
    <d2p1:KeyValueOfstringanyType> 
     <d2p1:Key>x</d2p1:Key> 
     <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:double">0.5</d2p1:Value> 
    </d2p1:KeyValueOfstringanyType> 
    <d2p1:KeyValueOfstringanyType> 
     <d2p1:Key>y</d2p1:Key> 
     <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:double">1.25</d2p1:Value> 
    </d2p1:KeyValueOfstringanyType> 
    <d2p1:KeyValueOfstringanyType> 
     <d2p1:Key>age</d2p1:Key> 
     <d2p1:Value xmlns:d4p1="http://www.w3.org/2001/XMLSchema" i:type="d4p1:int">4</d2p1:Value> 
    </d2p1:KeyValueOfstringanyType> 
    <d2p1:KeyValueOfstringanyType> 
     <d2p1:Key>list-of-strings</d2p1:Key> 
     <d2p1:Value> 
      <d2p1:string>one string</d2p1:string> 
      <d2p1:string>two string</d2p1:string> 
      <d2p1:string>last string</d2p1:string> 
     </d2p1:Value> 
    </d2p1:KeyValueOfstringanyType> 
</Attributes> 

注意list-of-strings底有。它有所有的值,但沒有任何表示這是一個List<string>或任何東西。

處理這種情況的正確方法是什麼?

回答

8

嘗試使用KnownTypeAttribute,以便DataContractSerializer知道List<string>類型。不幸的是,這似乎違背了你之前不必知道類型的想法。

我在下面的代碼,它使用DataContractSerializer連載含有List<string>一個Dictionary<string, object>此基礎:

Dictionary<string,object> dictionary = new Dictionary<string, object>(); 

dictionary.Add("k1", new List<string> { "L1", "L2", "L3" }); 

List<Type> knownTypes = new List<Type> { typeof(List<string>) }; 
DataContractSerializer serializer = new DataContractSerializer(typeof(Dictionary<string,object>), knownTypes); 
MemoryStream stream = new MemoryStream(); 

serializer.WriteObject(stream, dictionary); 

StreamReader reader = new StreamReader(stream); 

stream.Position = 0; 
string xml = reader.ReadToEnd(); 

如果knownTypes沒有提供給DataContractSerializer,它拋出一個異常。

SerializationException:類型 'System.Collections.Generic.List`1 [[System.String,mscorlib程序, 版本= 4.0.0.0,文化=中性公鑰= b77a5c561934e089]]' 與數據合同名 'ArrayOfstring:http://schemas.microsoft.com/2003/10/Serialization/Arrays' 不是預期的。考慮使用DataContractResolver或通過使用KnownTypeAttribute屬性或將其添加到傳遞給DataContractSerializer的已知類型的 列表,將靜態未知的任何 類型添加到已知類型列表中 - 例如, 。

0

WCF沒有辦法知道你有什麼是List<string>存在的方式 - 請注意,所有其他<Value>元素都有「類型提示」(第i:type屬性)。如果你想反序列化它,它需要有標記,你還需要告訴WCF List<string>是一個「已知類型」--見下文。有關已知類型(以及爲什麼需要它們)的更多信息,請參見web中的manygoodresources

public class StackOverflow_7620718 
{ 
    public static void Test() 
    { 
     Dictionary<string, object> dict = new Dictionary<string, object> 
     { 
      { "name", "Test object" }, 
      { "x", 0.5 }, 
      { "y", 1.25 }, 
      { "age", 4 }, 
      { "list-of-strings", new List<string> { "one string", "two string", "last string" } } 
     }; 
     MemoryStream ms = new MemoryStream(); 
     XmlWriter w = XmlWriter.Create(ms, new XmlWriterSettings 
     { 
      Indent = true, 
      Encoding = new UTF8Encoding(false), 
      IndentChars = " ", 
      OmitXmlDeclaration = true, 
     }); 
     DataContractSerializer dcs = new DataContractSerializer(dict.GetType(), new Type[] { typeof(List<string>) }); 
     dcs.WriteObject(w, dict); 
     w.Flush(); 
     Console.WriteLine(Encoding.UTF8.GetString(ms.ToArray())); 
     ms.Position = 0; 
     Console.WriteLine("Now deserializing it:"); 
     Dictionary<string, object> dict2 = (Dictionary<string, object>)dcs.ReadObject(ms); 
     foreach (var key in dict2.Keys) 
     { 
      Console.WriteLine("{0}: {1}", key, dict2[key].GetType().Name); 
     } 
    } 
} 
相關問題