Intereting Posts
Как я могу извлечь строку из ячейки excel? Объекты привязки DataGridView C # Правило для проверки равенства двух удвоений в C #? Как добавить tags @html с помощью javascript? Сопоставление свойства с элементом коллекции Как выполнить код на сервере TFS после проверки пользователем кода как читать pdf-файл с пустым пространством (как есть) по строке в c # .net с помощью iTextsharp Каковы преимущества использования , а не в WCF Служба Windows не отображается в установленных сервисах (и, следовательно, не может запускаться) Как работает CompilationRelaxations.NoStringInterning? WPF: получить событие на панели прокрутки из Scrollviewer Как динамически заполнять treeview (C #) C # таймер останавливается после некоторого количества тиков автоматически Метод регистрации метода, который будет вызываться при возникновении события XpsDocument GetFixedDocumentSequence возвращает значение null для файлов, сгенерированных определенным компьютером

Как я могу сериализовать объект с свойством Dictionary ?

В приведенном ниже примере кода я получаю эту ошибку :

Элемент TestSerializeDictionary123.Customer.CustomProperties vom Typ System.Collections.Generic.Dictionary`2 [[System.String, mscorlib, Version = 2.0.0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089], [System.Object, mscorlib, Version = 2.0 .0.0, Culture = neutral, PublicKeyToken = b77a5c561934e089]] не может быть сериализован, потому что он реализует IDictionary.

Когда я вывожу свойство словаря, он отлично работает.

Как я могу сериализовать этот объект Customer со свойством словаря? Или какой тип замены для словаря я могу использовать, это будет сериализуемо?

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 customers = Customer.GetCustomers(); Console.WriteLine("--- Serializing ------------------"); foreach (var customer in customers) { Console.WriteLine("Serializing " + customer.GetFullName() + "..."); string xml = XmlHelpers.SerializeObject(customer); Console.WriteLine(xml); Console.WriteLine("Deserializing ..."); Customer customer2 = XmlHelpers.DeserializeObject(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(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(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 CustomProperties { get; set; } private int internalValue = 23; public static List GetCustomers() { List customers = new List(); 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 + ")"; } } } 

В нашем приложении мы закончили использование:

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

вместо:

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

который решил проблему, поскольку DatacontractSerializer поддерживает словарь.

Еще одно решение заключается в том, что в приведенном выше примере также работает и механизм универсального универсального словаря XML Serializable Generic Dictionary , и долгое обсуждение этой ссылки у людей, использующих его, может быть полезно для людей, работающих с этой проблемой.

Вот общий class словаря, который знает, как сериализовать себя:

  public class XmlDictionary : Dictionary, 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)); reader.Read(); // Why is this necessary? var list = (List)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(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); } } 

Вы не можете (не делать все сами, что ужасно); сериализатор xml не будет иметь понятия, что делать с object , поскольку он не включает метаданные типа в формате проводов. Один (хакерский) вариант будет передавать эти все как строки для целей сериализации, но тогда у вас есть много дополнительного кода синтаксического анализа (и т. Д.) Для записи.

Вместо этого вы можете использовать двоичную сериализацию . (Просто убедитесь, что все ваши classы отмечены как [Serializable] . Конечно, это не будет в формате XML, но вы не указали это как требование 🙂

Я только что нашел это сообщение в блоге Ракеша Раджана, в котором описывается одно возможное решение:

Переопределите XmlSerialization, создав тип, реализующий class System.Xml.Serialization.IXmlSerializable. Определите, как вы хотите, чтобы объект был сериализован в XML в методе WriteXml, и определите, как вы могли бы воссоздать объект из строки xml в методе ReadXml.

Но это не сработает, поскольку ваш словарь содержит object а не определенный тип.

Как пометить class Customer как DataContract и его свойства как DataMembers. DataContract serializer сделает сериализацию для вас.

Попробуйте выполнить сериализацию через двоичный файл

 private void Deserialize() { try { var f_fileStream = File.OpenRead(@"dictionarySerialized.xml"); var f_binaryFormatter = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter(); myDictionary = (Dictionary)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) { ; } }