我有一个对象,我希望尽可能高效地在进程之间进行序列化和分发。对象本身具有对另一个对象的引用,如:
public class Foo
{
// Unique Identifier:
public int Id;
public Bar Bar;
}
public class Bar
{
// Unique Identifier:
public int Id;
}
问题是我只想序列化Foo并通过线路运行它。我宁愿不把Bar包含在我通过电线发送的内容中,因为它在另一边是已知的并且发送它会浪费我的“带宽”。
我想到的是:
在序列化时,我会序列化 Bar(Foo.Bar)的引用 int包含:Bar.Id(这是一个 Bar实例的唯一标识符)
只有Foo会被发送到 wire(包含int而不是 酒吧财产)。
在反序列化时,我会得到 int,从a中获取正确的Bar 存储库并将其放入 Foo.Bar属性。
这是限制被序列化对象图的任务的有效方法吗?有没有更好的方法呢?
答案 0 :(得分:5)
我不确定我在这里遗失了什么。
只需在您不想序列化的字段上使用NonSerialized
属性。
然后查看SerializationSurrogate以在反序列化时修复引用。
我使用类似的方法来二进制序列化LINQ2SQL对象。
更新:
更好的主意(忘记了这一点)。使用OnDeserializedAttribute,这很容易使用。
如果已经加载到内存中,使用Surrogate方法将允许您返回该对象的另一个实例。我使用它(在IronScheme中)来修复对运行时可能存在的盒装值类型的引用。
更新2:
您可以在following file的中间看到ISerializationSurrogate的示例。 (我提前为丑陋道歉)。
答案 1 :(得分:3)
您所描述的内容需要ISerializable
(自定义序列化)和常规BinaryFormatter
- 但是,protobuf-net可以让您简化(因此您不需要自己处理细节) ,虽然通常会在过程中缩小数据:
[ProtoContract]
public class Foo : ISerializable
{
// Unique Identifier:
[ProtoMember(1)]
public int Id;
public Bar Bar;
[ProtoMember(2)]
private int? BarProxy {
get {
if(Bar == null) return null;
return Bar.Id;
}
set {
if(value == null) { Bar = null; }
else { // fetch from repository
Bar = new Bar();
Bar.Id = value;
}
}
}
public Foo() { }
void ISerializable.GetObjectData(SerializationInfo info,
StreamingContext context) {
Serializer.Serialize(info, this);
}
protected Foo(SerializationInfo info, StreamingContext context) {
Serializer.Merge(info, this);
}
}
public class Bar
{
// Unique Identifier:
public int Id;
}
更简单的设置:
您使用的是什么序列化程序?
BinaryFormatter
一起,您将不想要的字段标记为[NonSerialized]
XmlSerializer
一起,将您不想要的成员标记为[XmlIgnore]
DataContractSerializer
,您只需不用[DataContract]
另外 - 也许考虑protobuf-net;这有一个非常有效的二元机制;比BinaryFormatter
答案 2 :(得分:2)
这听起来很可行,实际上你在Foo上实现了ISerializable接口,它可以控制你如何序列化Foo。
然后你实现相应的构造函数,你就可以访问你保存的状态,并可以将id拉出来。