31

我想序列化和反序列化对象而不必担心整个类图。

灵活性是关键。我希望能够序列化传递给我的任何对象,而无需整个对象图中所需的完整属性。

这意味着二进制序列化不是一个选项,因为它仅适用于其他 .NET 平台。我还想要一些人可以阅读的东西,因此可以被管理程序和其他解释器破译。

我在使用 DataContract、JSON 和 XML 序列化程序时发现了问题。

  • 大多数这些错误似乎都集中在列表/字典的序列化(即XML Serializable Generic Dictionary)上。
  • “将任何静态未知的类型添加到已知类型列表中 - 例如,通过使用 KnownTypeAttribute 属性或将它们添加到传递给 DataContractSerializer 的已知类型列表中。”

请根据实际经验而不是理论或阅读文章来回答。

4

12 回答 12

54

您是否考虑过序列化为 JSON 而不是 XML?

Json.NET有一个非常强大和灵活的序列化程序,它对 Hashtables/通用字典没有问题,并且不需要任何特定的属性。我知道是因为我写的:)

它通过序列化器上的各种选项为您提供大量控制,并允许您通过为其创建 JsonConverter 来覆盖类型的序列化方式。

在我看来,JSON 比 XML 更具人类可读性,而 Json.NET 提供了编写格式良好的 JSON 的选项。

最后,该项目是开源的,因此您可以在需要时单步执行代码并进行修改。

于 2008-09-20T02:32:51.267 回答
3

如果我记得它对属性的作用是这样的:

[XmlArray("Foo")]
[XmlArrayItem("Bar")]
public List<BarClass> FooBars
{ get; set; }

如果你序列化这个,你会得到类似的东西:

<Foo>
    <Bar />
    <Bar />
</Foo>

当然,我可能应该听从专家的意见。这是来自 MS 的更多信息:http: //msdn.microsoft.com/en-us/library/system.xml.serialization.xmlarrayitemattribute.aspx

让我知道这是否适合你。

于 2008-09-20T01:23:08.313 回答
2

根据您的要求,听起来 Xml 序列化是最好的。

序列化时集合有哪些问题?如果您指的是不知道在 List 上使用什么属性或类似的东西,您可以尝试在您的属性上使用 XmlArray 属性。你绝对可以序列化一个集合。

于 2008-09-20T01:02:19.517 回答
1

XNA 框架中的 IntermediateSerializer 非常酷。你可以在http://blogs.msdn.com/shawnhar找到一堆使用它的教程

于 2008-09-20T00:47:59.410 回答
1

SOAP 序列化对我来说效果很好,即使对于没有标记为 [Serializable] 的对象也是如此

于 2008-09-20T00:51:08.997 回答
1

如果集合中的对象包含对同一集合中其他对象的任何引用,您将遇到集合序列化问题。如果存在任何类型的双指向,您最终会创建一个无法序列化的多映射。在我序列化自定义集合的每一个问题上,总是因为我需要一些附加功能,这些功能作为“典型”客户端-服务器应用程序的一部分工作得很好,然后作为消费者提供者的一部分惨遭失败-服务器应用程序。

于 2008-09-20T01:22:07.893 回答
1

把所有要序列化的类放到一个单独的程序集中,然后用sgen工具生成一个序列化程序集序列化成XML。使用 XML 属性来控制序列化。

如果您需要自定义序列化程序集(并且您需要它来支持不是 IXmlSerializable 的类和包含抽象节点的类),则指示 sgen 将源代码转储到单独的文件中,然后将其添加到您的解决方案中。然后,您可以根据需要对其进行修改。

http://msdn.microsoft.com/en-us/library/bk3w6240(VS.80).aspx

FWIW,我已经设法使用这种技术序列化整个 AdsML 框架(超过 400 个类)。它确实需要大量的手动定制,但如果您考虑框架的大小,就无法解决这个问题。(我使用了一个单独的工具从 XSD 转到 C#)

于 2008-09-20T01:35:08.533 回答
1

我同意基于 DataContract 的序列化方法(到 JSON、XML 等)比我想要的要复杂一些。

如果您尝试获取 JSON,请查看http://msdn.microsoft.com/en-us/library/system.web.script.serialization.javascriptserializer.aspx

它是 MS AJAX 扩展的一部分。诚然,它在 .NET 3.5 中被标记为已过时,但 ScottGu 在他的博客评论中提到 ( http://weblogs.asp.net/scottgu/archive/2007/10/01/tip-trick-building-a-tojson-extension -method-using-net-3-5.aspx#4301973)他不确定为什么,应该支持更长的时间。

于 2008-09-20T10:07:05.637 回答
0

最简单的做法是使用 Serializable 属性标记您的对象,然后使用二进制格式化程序来处理序列化。如果任何包含的对象也被标记为可序列化,则整个类图不应该成为问题。

于 2008-09-20T00:47:51.127 回答
0

也许更有效的方法是使用 BinaryFormatter 进行序列化

复制自http://blog.paranoidferret.com/index.php/2007/04/27/csharp-tutorial-serialize-objects-to-a-file/

using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;

public class Serializer
{
   public Serializer()
   {
   }

   public void SerializeObject(string filename,
                  ObjectToSerialize objectToSerialize)
   {
      Stream stream = File.Open(filename, FileMode.Create);
      BinaryFormatter bFormatter = new BinaryFormatter();
      bFormatter.Serialize(stream, objectToSerialize);
      stream.Close();
   }

   public ObjectToSerialize DeSerializeObject(string filename)
   {
      ObjectToSerialize objectToSerialize;
      Stream stream = File.Open(filename, FileMode.Open);
      BinaryFormatter bFormatter = new BinaryFormatter();
      objectToSerialize =
         (ObjectToSerialize)bFormatter.Deserialize(stream);
      stream.Close();
      return objectToSerialize;
   }
}
于 2008-09-20T02:14:54.880 回答
0

对于互操作性,我们一直使用 Xml 序列化,并确保我们的类从头开始设计以正确执行。

我们创建一个 XSD 模式文档并使用 XSD.exe 从中生成一组类。这会生成部分类,因此我们然后创建一组相应的部分类来添加我们想要帮助我们填充类并在我们的应用程序中使用它们的额外方法(因为它们专注于序列化和反序列化并且有时使用起来有点困难)。

于 2008-09-20T02:44:42.890 回答
0

您应该使用 NetDataContractSerializer。它涵盖任何类型的对象图并支持泛型、列表、多态性(此处不需要 KnownType 属性)、递归等。唯一的缺点是您必须使用 [Serializable] / [DataContract] 属性标记所有类,但是经验表明,无论如何您都必须进行某种手动微调,因为并非所有成员都应该被持久化。它还序列化为 Xml,尽管它的可读性值得怀疑。

我们有与您相同的要求并选择了此解决方案。

于 2008-09-20T09:56:36.673 回答