2010-01-13 57 views
11

Trong đoạn mã ví dụ dưới đây, tôi nhận được lỗi này :Làm thế nào tôi có thể tuần tự hóa một đối tượng bằng thuộc tính Dictionary <string, object>?

tử TestSerializeDictionary123.Customer.CustomProperties vom Typ System.Collections.Generic.Dictionary`2 [[System.String, mscorlib, phiên bản = 2.0.0.0, Văn hóa = trung tính, PublicKeyToken = b77a5c561934e089], [System.Object, mscorlib, Version = 2.0.0.0, Văn hóa = trung tính, PublicKeyToken = b77a5c561934e089]] có thể không được đăng vì nó triển khai IDictionary.

Khi tôi lấy thuộc tính Từ điển, nó hoạt động fine.

Làm cách nào để có thể tuần tự hóa đối tượng Khách hàng này bằng thuộc tính từ điển? Hoặc tôi có thể sử dụng loại thay thế nào cho Từ điển có thể được tuần tự hóa?

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

namespace TestSerializeDictionary123 
{ 
    public class Program 
    { 
     static void Main(string[] args) 
     { 
      List<Customer> customers = Customer.GetCustomers(); 

      Console.WriteLine("--- Serializing ------------------"); 

      foreach (var customer in customers) 
      { 
       Console.WriteLine("Serializing " + customer.GetFullName() + "..."); 
       string xml = XmlHelpers.SerializeObject<Customer>(customer); 
       Console.WriteLine(xml); 
       Console.WriteLine("Deserializing ..."); 
       Customer customer2 = XmlHelpers.DeserializeObject<Customer>(xml); 
       Console.WriteLine(customer2.GetFullName()); 
       Console.WriteLine("---"); 
      } 

      Console.ReadLine(); 
     } 
    } 

    public static class StringHelpers 
    { 
     public static String UTF8ByteArrayToString(Byte[] characters) 
     { 
      UTF8Encoding encoding = new UTF8Encoding(); 
      String constructedString = encoding.GetString(characters); 
      return (constructedString); 
     } 

     public static Byte[] StringToUTF8ByteArray(String pXmlString) 
     { 
      UTF8Encoding encoding = new UTF8Encoding(); 
      Byte[] byteArray = encoding.GetBytes(pXmlString); 
      return byteArray; 
     } 
    } 

    public static class XmlHelpers 
    { 
     public static string SerializeObject<T>(object o) 
     { 
      MemoryStream ms = new MemoryStream(); 
      XmlSerializer xs = new XmlSerializer(typeof(T)); 
      XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8); 
      xs.Serialize(xtw, o); 
      ms = (MemoryStream)xtw.BaseStream; 
      return StringHelpers.UTF8ByteArrayToString(ms.ToArray()); 
     } 

     public static T DeserializeObject<T>(string xml) 
     { 
      XmlSerializer xs = new XmlSerializer(typeof(T)); 
      MemoryStream ms = new MemoryStream(StringHelpers.StringToUTF8ByteArray(xml)); 
      XmlTextWriter xtw = new XmlTextWriter(ms, Encoding.UTF8); 
      return (T)xs.Deserialize(ms); 
     } 
    } 

    public class Customer 
    { 
     public int Id { get; set; } 
     public string FirstName { get; set; } 
     public string LastName { get; set; } 
     public string Street { get; set; } 
     public string Location { get; set; } 
     public string ZipCode { get; set; } 
     public Dictionary<string,object> CustomProperties { get; set; } 

     private int internalValue = 23; 

     public static List<Customer> GetCustomers() 
     { 
      List<Customer> customers = new List<Customer>(); 
      customers.Add(new Customer { Id = 1, FirstName = "Jim", LastName = "Jones", ZipCode = "23434" }); 
      customers.Add(new Customer { Id = 2, FirstName = "Joe", LastName = "Adams", ZipCode = "12312" }); 
      customers.Add(new Customer { Id = 3, FirstName = "Jack", LastName = "Johnson", ZipCode = "23111" }); 
      customers.Add(new Customer { Id = 4, FirstName = "Angie", LastName = "Reckar", ZipCode = "54343" }); 
      customers.Add(new Customer { Id = 5, FirstName = "Henry", LastName = "Anderson", ZipCode = "16623" }); 
      return customers; 
     } 

     public string GetFullName() 
     { 
      return FirstName + " " + LastName + "(" + internalValue + ")"; 
     } 

    } 
} 

Trả lời

14

Trong ứng dụng của chúng tôi, chúng tôi đã kết thúc bằng:

DataContractSerializer xs = new DataContractSerializer(typeof (T)); 

thay vì:

XmlSerializer xs = new XmlSerializer(typeof (T)); 

mà giải quyết vấn đề như DataContractSerializer hỗ trợ từ điển.

Giải pháp khác là giải pháp XML Serializable Generic Dictionary cũng hoạt động trong ví dụ trên và có một cuộc thảo luận dài tại liên kết đó từ những người sử dụng nó, có thể hữu ích cho những người làm việc với vấn đề này.

+0

Trong khi DataContractSerializer là một gợi ý tốt, nó không bao gồm tất cả các kịch bản và chắc chắn không cung cấp cùng mức độ chi tiết và định nghĩa như XmlSerializer. –

0

Tôi vừa tìm thấy blog post by Rakesh Rajan này trong đó mô tả một giải pháp khả thi:

Override XmlSerialization bằng cách làm cho các loại thực hiện các lớp System.Xml.Serialization.IXmlSerializable. Xác định cách bạn muốn đối tượng được tuần tự hóa trong XML trong phương thức WriteXml và xác định cách bạn có thể tạo lại đối tượng từ chuỗi xml trong phương thức ReadXml.

Nhưng điều này sẽ không hoạt động khi Từ điển của bạn chứa object thay vì loại cụ thể.

4

Bạn không thể (không tự làm tất cả, điều đó thật kinh khủng); bộ nối tiếp xml sẽ không có manh mối phải làm gì với object vì nó không bao gồm siêu dữ liệu loại ở định dạng dây. Một (hacky) tùy chọn sẽ được dòng này tất cả như là chuỗi cho mục đích serialization, nhưng sau đó bạn có rất nhiều phân tích thêm (vv) mã để viết.

+0

Tôi sẽ phải giảm bớt bạn, vì đã đề xuất không thể thực hiện được. Nó bắt nguồn từ việc giải thích câu hỏi này khi chỉ muốn XML serialization, tuy nhiên, tôi cảm thấy mình nên làm một phần để ngăn chặn thông tin sai lệch có thể xảy ra :) Hy vọng OP có thể làm rõ nếu anh ta chỉ muốn XML serialization, hoặc bài viết của bạn có thể Điều chỉnh cho phù hợp. –

+0

Thẻ xml-serialization có trong câu hỏi, cho thấy OP quan tâm đến việc sắp xếp XML. –

0

Điều gì về việc đánh dấu Lớp khách hàng là DataContract và các thuộc tính của nó là DataMembers. DataContract serializer sẽ làm serialization cho bạn.

1

Thay vào đó, bạn có thể sử dụng Binary serialization. (Chỉ cần đảm bảo tất cả các lớp học của bạn được đánh dấu là [Serializable].Tất nhiên, nó sẽ không được ở định dạng XML, nhưng bạn không liệt kê đó là một yêu cầu :)

9

Dưới đây là một lớp từ điển chung mà biết làm thế nào để serialize bản thân:

public class XmlDictionary<T, V> : Dictionary<T, V>, IXmlSerializable { 
    [XmlType("Entry")] 
    public struct Entry { 
     public Entry(T key, V value) : this() { Key = key; Value = value; } 
     [XmlElement("Key")] 
     public T Key { get; set; } 
     [XmlElement("Value")] 
     public V Value { get; set; } 
    } 
    System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() { 
     return null; 
    } 
    void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) { 
     this.Clear(); 
     var serializer = new XmlSerializer(typeof(List<Entry>)); 
     reader.Read(); // Why is this necessary? 
     var list = (List<Entry>)serializer.Deserialize(reader); 
     foreach (var entry in list) this.Add(entry.Key, entry.Value); 
     reader.ReadEndElement(); 
    } 
    void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) { 
     var list = new List<Entry>(this.Count); 
     foreach (var entry in this) list.Add(new Entry(entry.Key, entry.Value)); 
     XmlSerializer serializer = new XmlSerializer(list.GetType()); 
     serializer.Serialize(writer, list); 
    } 
    } 
+0

Điều này không giải quyết được vấn đề về việc có từ điển trong đó các giá trị là 'đối tượng'. – jsirr13

0

Hãy thử Serializating qua BinaryFormatter

private void Deserialize() 
    { 
     try 
     { 
      var f_fileStream = File.OpenRead(@"dictionarySerialized.xml"); 
      var f_binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
      myDictionary = (Dictionary<string, myClass>)f_binaryFormatter.Deserialize(f_fileStream); 
      f_fileStream.Close(); 
     } 
     catch (Exception ex) 
     { 
      ; 
     } 
    } 
    private void Serialize() 
    { 
     try 
     { 
      var f_fileStream = new FileStream(@"dictionarySerialized.xml", FileMode.Create, FileAccess.Write); 
      var f_binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); 
      f_binaryFormatter.Serialize(f_fileStream, myDictionary); 
      f_fileStream.Close(); 
     } 
     catch (Exception ex) 
     { 
      ; 
     } 
    } 
Các vấn đề liên quan