2011-10-01 18 views
6

Tôi đang sử dụng DataContractSerializer để tuần tự hóa đối tượng có chứa thành viên Dictionary<string,object>, được đánh dấu bằng [DataMember()]. Ý tưởng là để có một túi linh hoạt của các thuộc tính đối tượng, và tôi không biết những gì các thuộc tính có thể được.DataContractSerializer và Dictionary <string, object> không thành công khi đọc

này hoạt động tuyệt vời khi tôi đang đưa int, doublestring đối tượng vào từ điển, nhưng khi tôi đặt một List<string> trong nó không deserialize đối tượng với:

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

Toàn bộ từ điển là serialized để XML và có vẻ khá hợp lý:

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

Lưu ý rằng list-of-strings ở cuối đó. Nó có tất cả các giá trị nhưng không có gì chỉ ra rằng đó là một số List<string> hoặc bất kỳ thứ gì.

Cách xử lý đúng tình huống này là gì?

Trả lời

8

Hãy thử sử dụng KnownTypeAttribute để DataContractSerializer biết về loại List<string>. Thật không may, điều đó dường như đi ngược lại ý tưởng của bạn về việc không phải biết về các loại trước khi bàn tay.

tôi dựa trên các mã sau đây, trong đó sử dụng DataContractSerializer để serialize một Dictionary<string, object> chứa List<string>:

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

Nếu bạn knownTypes không được cung cấp cho DataContractSerializer, nó ném một ngoại lệ.

SerializationException: Loại 'System.Collections.Generic.List`1 [[System.String, mscorlib, Version = 4.0.0.0, Culture = trung tính, PublicKeyToken = b77a5c561934e089]]' với tên hợp đồng dữ liệu 'ArrayOfstring: http: //schemas.microsoft.com/2003/10/Serialization/Arrays' không được mong đợi. Cân nhắc sử dụng DataContractResolver hoặc thêm bất kỳ loại nào không được biết đến tĩnh vào danh sách các loại đã biết - ví dụ: bằng cách sử dụng thuộc tính KnownTypeAttribute hoặc thêm chúng vào danh sách các loại đã biết được chuyển đến DataContractSerializer.

0

WCF không có cách nào để biết rằng những gì bạn có là một List<string> đó - nhận thấy rằng tất cả các yếu tố khác <Value> có một "kiểu gợi ý" (i: loại thuộc tính). Nếu bạn muốn deserialize nó, nó cần phải có đánh dấu, và bạn cũng cần phải nói với WCF rằng List<string> là một "loại đã biết" - xem dưới đây. Để biết thêm thông tin về các loại đã biết (và lý do chúng cần thiết) có manygoodresources trong số web.

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); 
     } 
    } 
} 
Các vấn đề liên quan