什么是.NET对象最灵活但又易于实现的序列化?

时间:2020-03-06 14:28:24  来源:igfitidea点击:

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

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

That means that Binary Serialization
  is not an option as it only works with
  the other .NET Platforms.  I would
  also like something readable by a
  person, and thus decipherable by a
  management program and other
  interpreters.

我发现使用DataContract,JSON和XML序列化器存在问题。

  • 这些错误中的大多数似乎都围绕列表/字典的序列化(即XML可序列化的通用字典)。
  • "将任何静态未知的类型添加到已知类型的列表中,例如,通过使用KnownTypeAttribute属性或者将它们添加到传递给DataContractSerializer的已知类型的列表中。"

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

解决方案

最简单的方法是使用Serializable属性标记对象,然后使用二进制格式器处理序列化。如果所有包含的对象也都标记为Serializable,则整个类图应该不是问题。

XNA Framework中的IntermediateSerializer非常酷。我们可以在http://blogs.msdn.com/shawnhar上找到大量使用它的教程。

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

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

序列化时集合有什么问题?如果我们指的是不知道要在列表或者类似内容上使用哪些属性,则可以尝试使用
属性上的XmlArray属性。我们绝对可以序列化一个集合。

如果集合中的对象包含对同一集合中其他对象的任何引用,则集合序列化会遇到问题。如果存在任何类型的双向指向,最终将创建一个无法序列化的多重映射。在我曾经序列化过一个自定义集合的每个问题上,总是因为我需要一些添加功能而使其在"典型"客户端-服务器应用程序中工作正常,然后在作为消费者提供者的一部分中不幸失败了-服务器应用程序。

如果我还记得,它可以通过一个属性来完成类似的工作:

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

如果我们将此序列化,则会得到以下内容:

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

当然,我可能应该请专家处理。这是来自MS的更多信息:http://msdn.microsoft.com/zh-cn/library/system.xml.serialization.xmlarrayitemattribute.aspx

让我知道是否适合我们。

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

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

http://msdn.microsoft.com/zh-cn/library/bk3w6240(VS.80).aspx

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

也许更有效的方法是使用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;
   }
}

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

Json.NET具有强大而灵活的序列化器,它对哈希表/通用字典没有任何问题,并且不需要任何特定的属性。我知道是因为我写的:)

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

在我看来,JSON比XML更具可读性,并且Json.NET提供了编写格式正确的JSON的选项。

最后,该项目是开源的,因此我们可以进入代码并根据需要进行修改。

为了实现互操作性,我们一直使用Xml序列化,并确保我们的类是从头开始设计的,以正确地进行操作。

我们创建一个XSD架构文档,并使用XSD.exe从中生成一组类。这会生成部分类,因此我们随后创建了一组对应的部分类,以添加想要帮助我们填充类并在我们的应用程序中使用它们的额外方法(因为它们专注于序列化和反序列化,有时很难使用)。

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

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

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

如果我们尝试获取JSON,请访问http://msdn.microsoft.com/zh-cn/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),他不确定为什么,应该再支持一点时间。