我需要将一些类和数据结构保存到文件中。我的第一反应是使用XML或二进制序列化,但这变成了一场噩梦。我有一组不是序列化的类(私有setter,没有无参数构造函数,没有Serialization属性,字典等)。考虑到我不能改变那些课程,我该怎么办?有没有解决方法,仍然使用序列化?
我是否必须编写所有代码来编写属性,集合等?
答案 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)
答案 2 :(得分:0)
我会使用代码生成工具(mygeneration,T4,无论如何)来生成要序列化的DTO ......
答案 3 :(得分:0)
不是一个简单的解决方法。
您可能只想序列化/反序列化类中的字段(私有和公共),并以递归方式执行。您可能需要使用反射来获取它们。不要对属性进行de / serialize,因为在设置属性值时可能会出现副作用。您还必须递归地/序列化所有作为对象的字段。挑战在于知道应该停在哪里。
您必须对如何使用反射反序列化序列化对象做一些大的猜测。我必须假设这些对象的某些字段包含对其他对象的引用,并且您必须知道如何遍历所有这些对象。
此外,您必须调用参数化构造函数,并希望在使用反射设置字段时不会造成太大的损害。
简而言之,您可能最好创建一组特殊用途的包装类,它可以从序列化格式重新创建专有类。然后可以使您的特殊目的类可序列化。这不是一项简单的任务。
也就是说,代码可能能够简化识别类中所有字段的任务。
答案 4 :(得分:0)
另一种选择是使用适配器模式。
好消息是你不必改变原来的课程。 坏消息是,您可能最终编写的代码是第一个“不可更改”类中存在的代码的两倍。
最终会有2个新类:适配器和新的可序列化类。
这个想法是适配器知道如何通过检查不可序列化的类来创建serizliable类。换句话说(可序列化为不可序列化)你可以再次使用适配器(当然,我假设您的私有setter实际上是通过参数化构造函数设置的。)
答案 5 :(得分:0)
这有两个独立的部分:
对于第一部分,如果你不能改变你想要序列化/反序列化的类,那么你真的只需要通过反射进行深层复制。
对于序列化,请遍历存储其值的类的每个成员。
使用您想要存储的媒体,例如XML,并将这些值写入磁盘。
对于反序列化,从文件中读取值,创建对象的新实例并使用反射来设置所有值。
如果你获得/设置所有成员,你将拥有一个处于相同状态的对象。 (如果您有复杂的成员,则可能需要以递归方式遍历所有对象。)
至于如何将数据存储在磁盘上,xml或二进制文件都可以正常工作。如果你想看到它并让它具有人类可读性,那么请使用XML。 (我建议你最初尝试这个,因为它会使调试变得更容易。)
答案 6 :(得分:0)
这实际上取决于问题的规模和所需的性能。
如果您有1个问题类,我只需编写一个可以序列化/反序列化该类的代理类。如果您正在谈论100个类,您可能需要使用支持所有复杂性的序列化框架。没有无参数构造是一场噩梦,无论你编写或使用什么序列化框架,你都需要预先知道params传递给构造函数。私人制定者/词典/列表等不是太大的问题。
我为媒体浏览器编写了一个mini-serialization框架,它是BSD。我的重点是性能,但我使用的技术可以适应你的问题。类似地,可以使用Marc protocol buffers中使用的技术。
如果性能根本不重要,那么一个相当简单的序列化框架可以很快地编码,使用反射,当你试图保持高效的东西时,东西变得很难。