Ian*_*Ian 6 c# serialization object-graph
我想知道是否有一种方法可以创建一个序列化对象图的树/视图,以及是否有人有任何指针?编辑我们的目标是,由于某些原因我们应该遇到反序列化问题,我们实际上可以查看/生成序列化数据的报告,以帮助我们在调试代码之前确定问题的原因.此外,我希望将来扩展它以采用两个流(版本1,版本2)并突出显示它们之间的差异,以帮助确保我们在代码更改期间不会意外删除有趣的信息./编辑
传统上我们使用Soap或XML序列化,但是这些对于我们的需求变得太受限制,而二进制序列化通常会做我们需要的所有事情.之所以没有采用,是因为查看序列化内容以帮助修复升级问题等更加困难.
所以我开始考虑尝试创建序列化信息的视图.我可以在一定程度上从ISerializable构造函数执行此操作:
public A(SerializationInfo info, StreamingContext context)
{}
Run Code Online (Sandbox Code Playgroud)
给定序列化信息,我可以反映m_data成员并查看实际的序列化内容.这种方法的问题是
我已经看过ObjectManager类,但这适用于现有的对象图,而我需要能够从数据流中工作.我查看了BinaryFormatted,它使用了ObjectReader和__BinaryParser,挂钩到ObjectManager(我认为它将拥有整个内容,可能只是在一个平面列表中),但要复制它或通过反射调用它(2)这三个类是内部的)似乎相当多的工作,所以我想知道是否有更好的方法.
为了实现您所描述的目的,您必须从流中反序列化整个对象图,而不知道它被序列化的类型。但这是不可能的,因为序列化器不存储此类信息。AFAIK 它的工作方式如下。假设您有几种类型:
class A { bool p1 }
class B { string p1; string p2; A p3}
// instantiate them:
var b = new B { p1 = "ppp1", p2 = "ppp2", p3 = new A { p1 = true} };
Run Code Online (Sandbox Code Playgroud)
当序列化程序写入此对象时,它开始以某种特定顺序(我假设按字母顺序)遍历对象图并写入对象类型,然后写入其内容。所以你的二进制流会像这样:
[B:[string:ppp1][string:ppp2][A:[bool:true]]]
Run Code Online (Sandbox Code Playgroud)
你看,这里只有值和它们的类型。但顺序是隐含的——就像它被写下来一样。所以,如果你改变你的对象 B,假设
class B { A p1; string p3; string p3;}
Run Code Online (Sandbox Code Playgroud)
Serialzer将会失败,因为它会尝试将字符串实例(首先被序列化)分配给指向A的指针。您可以尝试对二进制序列化的工作原理进行逆向工程,然后您也许能够创建序列化对象的动态树。但这需要付出相当大的努力。
为此,我将创建与此类似的类:
class Node
{
public string NodeType;
public List<Node> Children;
public object NodeValue;
}
Run Code Online (Sandbox Code Playgroud)
然后,当您从流中读取数据时,您可以创建这些节点,并重新创建整个序列化树并对其进行分析。