好吧,之前我已经问了一些关于序列化的问题,但是我仍然被卡住了 - 所以我想我只是吐出我的整个案例而不是子问题,希望有人能指出我的问题正确的方向:)
我的应用程序类似于Apple的“Quartz Composer”,这意味着我有一个连接节点的树状结构。
节点由INode接口定义;实际的节点类型/类是使用MEF从DLL导入的,因此在编译时将不知道节点类型。
节点已连接,因此可以并且将发生双向链接。
我想将我的'组合' - 整个节点树 - 保存到一个文件中,最好是人类可读的XML。我真的想避免保存为专有格式!
所以我需要序列化的是:
一个对象树,其类可以在运行时导入(因此事先不知道),它可以包含双向链接。
最重要的是,我想存储已使用节点类的版本信息,因此可以判断是否使用某个节点类的旧版本存储“组合”而不是使用的dll /节点当前应用程序中的类。
以前我指的是DataContractSerializer,它似乎是一个存储我的树并完全支持双向链接的漂亮工具。
但是,如果我想序列化我的树(接口IComposition),它开始抱怨未知类型 - 我必须指定序列化树时可能遇到的每种特定类型......
而且我也没办法指定哪个汇编版本用于特定的节点类。
不知何故,首先枚举我的整个树以找出已使用的节点类,将它们添加到已知类型列表,然后序列化是不正确的。
即使这样,我也必须找到一种方法来为输出数据添加一个部分,为使用的类指定版本信息。
也许我是唯一一个遇到这个问题的人,但我真的希望其他人遇到并在此之前克服这个问题 - 最好用一个优雅的解决方案;) 我可以想象这不是标准.NET序列化程序可以处理的东西,但也许有一些第三方(免费,开源甚至?)实现?
答案 0 :(得分:0)
您可以使用BinaryFormatter或SoapFormatter完成此操作。这些格式化程序使用任意对象图,并将处理它们遇到的任何对象(只要对象的类型标记为[Serializable]
)并且将正确保留循环引用。如果您想知道对象是如何序列化的,请使用SoapFormatter,它将输出XML。
请注意,任何可按需加载的程序集都必须位于GAC中,否则运行时将无法找到它们。
要处理版本控制,您可以执行以下操作:
[Serializable]
public class SomeVersionedClass : IDeserializationCallback
{
private const int CURRENT_VERSION = 10;
private int version = CURRENT_VERSION;
void IDeserializationCallback.OnDeserialization(object sender)
{
if (version != CURRENT_VERSION)
throw new ApplicationException(
"Mismatch between serialized data version " + version +
" and required version " + CURRENT_VERSION + ".");
}
}
请注意,您可以考虑将数据从先前版本布局迁移到新版本,而不是抛出异常。此外,请注意从类中删除序列化字段将完全阻止将来反序列化,因此如果您计划允许从不再使用的字段迁移,则必须保留该字段,以便先前版本可以正确反序列化(当然,这样你就可以获得数据来迁移它。)