【问题标题】:Serializing lists/dictionaries序列化列表/字典
【发布时间】:2012-11-07 19:52:06
【问题描述】:

我有一个应用程序需要序列化自定义对象并将其发送到 Windows 服务,自定义对象包含 2 个自定义对象列表和一个 int、string 字典。当我尝试序列化对象时,我收到错误消息:

There was an error generating the XML document.

我搜索了一下,发现这通常是由于其中一种数据类型没有正确设置序列化。所以我已经完成并验证了所有自定义类的序列化,据我所知,它设置正确。

我现在的问题是,默认情况下列表和字典是可序列化的还是需要做些什么来序列化它们?或者,是否有更好的方法来序列化要在可执行文件之间传递的自定义对象集合?

编辑:

主自定义类:

[Serializable]
class MoveInInfoRequest : ServerRequestData
{ }
[Serializable]
[XmlInclude(typeof(GetUnitTypesResponseData)), XmlInclude(typeof(VendorObj.RequiredFields)),
     XmlInclude(typeof(VendorObj.InsuranceChoice)), XmlInclude(typeof(VendorObj.ProrateSettings))]
public class MoveInInfoResponse : ServerResponseData
{
    public GetUnitTypesResponseData UnitTypesInfo
    { get; set; }
    public List<VendorObj.RequiredFields> RequiredFields 
    { get; set; }
    public Dictionary<int, String> RentalPeriods
    { get; set; }
    public List<VendorObj.InsuranceChoice> InsCoverageAmounts
    { get; set; }
    public VendorObj.ProrateSettings ProrateOptions
    { get; set; }
}

示例子类:其他两个类的设置与此类似,只是要长得多,但它们只使用默认数据类型。

<Serializable(), DataContract([Namespace]:="*companyNamespace*")> _
Public Class InsuranceChoice
    Public Sub New()
    End Sub
    <DataMember()> _
    Public InsuranceChoiceID As Integer
    <DataMember()> _
    Public CoverageDescription As String
    <DataMember()> _
    Public Premium As Decimal
    <DataMember()> _
    Public ActualCoverageAmount As Decimal

End Class

【问题讨论】:

  • 发布代码将有助于获得答案:)
  • 它们是可序列化的,是的。正如@Mihai 所说,代码会有所帮助。
  • List 和 Dictionary 是可序列化的,无需您做任何事情。显然,您在其中放入了一些不存在的东西,或者序列化了其他不存在的东西。
  • 这个问题不是特定于代码的,它更适合一般参考,因为我无法通过谷歌找到直接答案。但是我添加了主类和子类之一,以防出现明显错误......
  • My question now is, are lists and dictionaries serializable by default or does something need to be done in order to serialize them 可以序列化的内容和字段/属性取决于您使用的序列化程序。没有一般规律。例如,XmlSerializer 不需要 Serializable 属性,它仅由 BinaryFormatter 使用(?)

标签: c# serialization


【解决方案1】:

这取决于您尝试使用什么序列化它们。特别是,如果您使用的是XmlSerializer,Dictionary 对象是不可序列化的,但如果您使用的是DataContractSerializer,它们是不可序列化的。序列化列表应该没问题。

如果您想要 Xml 序列化的替代方案,您可以使用 Json.Net 序列化为 JSON。

参考资料:

Serialize Class containing Dictionary member

Serializing .NET dictionary

Why doesn't XmlSerializer support Dictionary?

http://theburningmonk.com/2010/05/net-tips-xml-serialize-or-deserialize-dictionary-in-csharp/

【讨论】:

  • 这是有道理的,因为我试图缩短 Rentalperiods 对象而不是编写新类。感谢您提供的链接,他们更清楚地说明了我遇到问题的原因。
【解决方案2】:

当涉及到序列化时,这是一个很常见的问题。

一个实现IDictionarycannot be serialized的集合

您可以使用 DataContractSerializer ,但更好的解决方案(在我看来)是创建您自己的 Dictionary 类,该类不继承自 IDictionary

可以找到此类类的示例here

在解决方案中实现类后,只需执行以下操作:

using System;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            var response = new MoveInInfoResponse
            {
                RentalPeriods = new SerializableDictionary<int, string> 
                { { 1, "Period 1" }, { 2, "Period 2" } }
            };

            string xml = Serialize(response);
        }

        static string Serialize(Object obj)
        {
            var serializer = new XmlSerializer(obj.GetType());
            var settings = new XmlWriterSettings { Indent = true, OmitXmlDeclaration = true };

            using (var stream = new StringWriter())
            {
                using (var writer = XmlWriter.Create(stream, settings))
                    serializer.Serialize(writer, obj);
                return stream.ToString();
            }
        }
    }

    [Serializable]
    public class MoveInInfoResponse
    {
        public SerializableDictionary<int, String> RentalPeriods
        { get; set; }
    }
}

生成以下 XML 文件:

<MoveInInfoResponse xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <RentalPeriods>
    <Item>
      <Key>
        <int>1</int>
      </Key>
      <Value>
        <string>Period 1</string>
      </Value>
    </Item>
    <Item>
      <Key>
        <int>2</int>
      </Key>
      <Value>
        <string>Period 2</string>
      </Value>
    </Item>
  </RentalPeriods>
</MoveInInfoResponse>

【讨论】:

  • 感谢您的工作。这在未来可能会派上用场。对于这个实现来说,有问题的数据成员是它自己的类更有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2013-10-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多