如何序列化未设计为序列化的类?

时间:2009-05-07 00:04:13

标签: c# xml-serialization

我需要将一些类和数据结构保存到文件中。我的第一反应是使用XML或二进制序列化,但这变成了一场噩梦。我有一组不是序列化的类(私有setter,没有无参数构造函数,没有Seri​​alization属性,字典等)。考虑到我不能改变那些课程,我该怎么办?有没有解决方法,仍然使用序列化?

我是否必须编写所有代码来编写属性,集合等?

7 个答案:

答案 0 :(得分:9)

使用JavaScriptSerializer。它位于System.Web.Script.Serialization命名空间中,并在System.Web.Extensions.dll程序集的3.5框架中实现。

使用此类,您可以序列化任何POCO,无论它是否标记为[Serializable]。您的程序不必是使用JSON序列化的Web应用程序。这是一个例子:

public class Unserializable
{
  public int Age { get; set; }
  public int ID { get; set; }
  public string Name { get; set; }
}

public class Program
{
  static void Main()
  {
    var u = new Unserializable
            {
              Age = 40,
              ID = 2,
              Name = "Betty"
            };
    var jser = new JavaScriptSerializer();
    var jsonText = jser.Serialize( u );
    // next line outputs {"Age":40,"ID":2,"Name":"Betty"}
    Console.WriteLine( jsonText );
  }
}

答案 1 :(得分:7)

听起来像...序列化代理人的工作!

转到http://msdn.microsoft.com/en-us/magazine/cc188950.aspx

概述。

答案 2 :(得分:0)

我会使用代码生成工具(mygeneration,T4,无论如何)来生成要序列化的DTO ......

答案 3 :(得分:0)

不是一个简单的解决方法。

您可能只想序列化/反序列化类中的字段(私有和公共),并以递归方式执行。您可能需要使用反射来获取它们。不要对属性进行de / serialize,因为在设置属性值时可能会出现副作用。您还必须递归地/序列化所有作为对象的字段。挑战在于知道应该停在哪里。

您必须对如何使用反射反序列化序列化对象做一些大的猜测。我必须假设这些对象的某些字段包含对其他对象的引用,并且您必须知道如何遍历所有这些对象。

此外,您必须调用参数化构造函数,并希望在使用反射设置字段时不会造成太大的损害。

简而言之,您可能最好创建一组特殊用途的包装类,它可以从序列化格式重新创建专有类。然后可以使您的特殊目的类可序列化。这不是一项简单的任务。

也就是说,代码可能能够简化识别类中所有字段的任务。

答案 4 :(得分:0)

另一种选择是使用适配器模式。

好消息是你不必改变原来的课程。 坏消息是,您可能最终编写的代码是第一个“不可更改”类中存在的代码的两倍。

最终会有2个新类:适配器和新的可序列化类。

这个想法是适配器知道如何通过检查不可序列化的类来创建serizliable类。换句话说(可序列化为不可序列化)你可以再次使用适配器(当然,我假设您的私有setter实际上是通过参数化构造函数设置的。)

Here's the pattern in detail.

答案 5 :(得分:0)

这有两个独立的部分:

  1. 提取/设置数据
  2. 从文件(或其他位置)存储/读取
  3. 对于第一部分,如果你不能改变你想要序列化/反序列化的类,那么你真的只需要通过反射进行深层复制。

    对于序列化,请遍历存储其值的类的每个成员。

    使用您想要存储的媒体,例如XML,并将这些值写入磁盘。

    对于反序列化,从文件中读取值,创建对象的新实例并使用反射来设置所有值。

    如果你获得/设置所有成员,你将拥有一个处于相同状态的对象。 (如果您有复杂的成员,则可能需要以递归方式遍历所有对象。)

    至于如何将数据存储在磁盘上,xml或二进制文件都可以正常工作。如果你想看到它并让它具有人类可读性,那么请使用XML。 (我建议你最初尝试这个,因为它会使调试变得更容易。)

答案 6 :(得分:0)

这实际上取决于问题的规模和所需的性能。

如果您有1个问题类,我只需编写一个可以序列化/反序列化该类的代理类。如果您正在谈论100个类,您可能需要使用支持所有复杂性的序列化框架。没有无参数构造是一场噩梦,无论你编写或使用什么序列化框架,你都需要预先知道params传递给构造函数。私人制定者/词典/列表等不是太大的问题。

我为媒体浏览器编写了一个mini-serialization框架,它是BSD。我的重点是性能,但我使用的技术可以适应你的问题。类似地,可以使用Marc protocol buffers中使用的技术。

如果性能根本不重要,那么一个相当简单的序列化框架可以很快地编码,使用反射,当你试图保持高效的东西时,东西变得很难。