C# 如何使用字典序列化对象<;字符串,对象>;财产?

C# 如何使用字典序列化对象<;字符串,对象>;财产?,c#,serialization,dictionary,xml-serialization,C#,Serialization,Dictionary,Xml Serialization,在下面的示例代码中,我得到一个错误: 元素 TestSerializeDictionary123.Customer.CustomProperties vom类型 System.Collections.Generic.Dictionary`2[[System.String, mscorlib,版本=2.0.0.0, 文化=中立, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib,版本=2.0.0.0, 文化=中立, PublicKe

在下面的示例代码中,我得到一个错误

元素 TestSerializeDictionary123.Customer.CustomProperties vom类型 System.Collections.Generic.Dictionary`2[[System.String, mscorlib,版本=2.0.0.0, 文化=中立, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib,版本=2.0.0.0, 文化=中立, PublicKeyToken=b77a5c561934e089]]can 无法序列化,因为它 实现IDictionary

当我取出Dictionary属性时,它会正常工作

如何使用dictionary属性序列化此客户对象?或者我可以使用哪种可序列化的字典替换类型?

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 + ")";
        }

    }
}
使用系统;
使用System.Collections.Generic;
使用System.Xml.Serialization;
使用System.IO;
使用System.Xml;
使用系统文本;
命名空间TestDictionary123
{
公共课程
{
静态void Main(字符串[]参数)
{
List customers=Customer.GetCustomers();
Console.WriteLine(“---序列化-------------------------------”);
foreach(客户中的var客户)
{
Console.WriteLine(“序列化”+customer.GetFullName()+”);
字符串xml=XmlHelpers.SerializeObject(客户);
Console.WriteLine(xml);
WriteLine(“反序列化…”);
customer2=XmlHelpers.DeserializeObject(xml);
Console.WriteLine(customer2.GetFullName());
Console.WriteLine(“--”);
}
Console.ReadLine();
}
}
公共静态类StringHelper
{
公共静态字符串UTF8ByteArrayToString(字节[]个字符)
{
UTF8Encoding=新的UTF8Encoding();
String constructedString=encoding.GetString(字符);
返回(构造字符串);
}
公共静态字节[]StringToUTF8ByteArray(字符串pXmlString)
{
UTF8Encoding=新的UTF8Encoding();
Byte[]byteArray=encoding.GetBytes(pXmlString);
乘火车返回;
}
}
公共静态类XmlHelpers
{
公共静态字符串序列化对象(对象o)
{
MemoryStream ms=新的MemoryStream();
XmlSerializer xs=新的XmlSerializer(typeof(T));
XmlTextWriter xtw=新的XmlTextWriter(ms,Encoding.UTF8);
序列化(xtw,o);
ms=(内存流)xtw.BaseStream;
返回StringHelpers.UTF8ByteArrayToString(ms.ToArray());
}
公共静态T反序列化对象(字符串xml)
{
XmlSerializer xs=新的XmlSerializer(typeof(T));
MemoryStream ms=新的MemoryStream(StringHelpers.StringToUTF8ByteArray(xml));
XmlTextWriter xtw=新的XmlTextWriter(ms,Encoding.UTF8);
返回(T)xs.反序列化(ms);
}
}
公共类客户
{
公共int Id{get;set;}
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共字符串Street{get;set;}
公共字符串位置{get;set;}
公共字符串ZipCode{get;set;}
公共字典CustomProperties{get;set;}
私人内部价值=23;
公共静态列表GetCustomers()
{
列出客户=新列表();
添加(新客户{Id=1,FirstName=“Jim”,LastName=“Jones”,ZipCode=“23434”});
添加(新客户{Id=2,FirstName=“Joe”,LastName=“Adams”,ZipCode=“12312”});
添加(新客户{Id=3,FirstName=“Jack”,LastName=“Johnson”,ZipCode=“23111”});
添加(新客户{Id=4,FirstName=“Angie”,LastName=“Reckar”,ZipCode=“54343”});
添加(新客户{Id=5,FirstName=“Henry”,LastName=“Anderson”,ZipCode=“16623”});
返回客户;
}
公共字符串GetFullName()
{
返回FirstName+“”+LastName+“”(“+internalValue+”);
}
}
}
我刚刚发现这一点,它描述了一种可能的解决方案:

通过使类型实现System.Xml.Serialization.IXmlSerializable类来重写XmlSerialization。定义希望在WriteXml方法中以XML序列化对象的方式,并定义如何从ReadXml方法中的XML字符串重新创建对象


但是这不起作用,因为你的字典包含一个
对象,而不是一个特定的类型。

你不能(除非你自己做,这很可怕);xml序列化程序不知道如何处理
对象
,因为它在wire格式中不包含类型元数据。一个(hacky)选项是,为了序列化的目的,将所有这些都作为字符串进行流式处理,但是您需要编写大量额外的解析(etc)代码。

如何将Customer类标记为DataContract,将其属性标记为DataMembers。DataContract序列化程序将为您进行序列化。

在我们的应用程序中,我们最终使用了:

DataContractSerializer xs = new DataContractSerializer(typeof (T));
而不是:

XmlSerializer xs = new XmlSerializer(typeof (T));
解决了DatacontractSerializer支持字典的问题


另一个解决方案是,在上面的示例中,该解决方案也有效,使用该解决方案的用户在该链接上进行了长时间的讨论,可能对处理此问题的用户有用。

您可以使用它。(只需确保所有类都标记为
[Serializable]
。当然,它不是XML格式,但您没有将其列为要求:)

这里有一个通用字典类,它知道如何序列化自己:

  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);
    }
  }
公共类XmlDictionary:字典,IXmlSerializable{
[XmlType(“条目”)]
公共结构条目{
公共输入(T键,V值
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)
        {
            ;
        }
    }