【发布时间】:2018-08-09 19:10:21
【问题描述】:
我在一个应用程序中使用 protobuf-net,该应用程序对来自(出于所有意图和目的)第 3 方 dll 的对象进行大量二进制序列化。结果,我不能在合约本身上使用 [Proto-] 属性,而是使用 RuntimeTypeModel 在运行时准备序列化程序,因为它遇到新类型。示例序列化程序包装器:
public static class ProtobufSerializer
{
public static byte[] Serialize<T>(T obj)
{
PrepareSerializer(typeof(T));
ProtoBuf.Serialize(memoryStream, obj);
}
public static T Deserialize<T>(byte[] bytes)
{
PrepareSerializer(typeof(T));
ProtoBuf.Serialize(memoryStream, obj);
}
}
我们可以安全地假设PrepareSerializer 能够准备RuntimeTypeModel 来序列化任何给定的类型。我在对象的反序列化方面遇到了一些问题,我必须利用DynamicType=true。例如,给定以下接口:
public interface IFoo
{
string Name {get;}
}
以及实现:
public class Foo : IFoo
{
public string Name {get;set;}
public Bar Bar {get;set;}
[OnDeserializing]
public void OnDeserializing(Type t)
{
PrepareSerializer(typeof(Foo));
}
}
public class Bar
{
public int Baz {get;set;}
}
PrepareSerializer 方法本质上会使用代理并生成一个大致相当于:
// registered surrogate for IFoo
[ProtoContract]
public class IFooSurrogate
{
[ProtoMember(1, DynamicType=true)]
public object Value
[OnSerializing]
public void OnSerializing(Type t)
{
PrepareSerializer(this.Value.GetType());
}
}
其中Value 由隐式转换器设置为等于IFoo 的实例。这在序列化期间工作正常(触发事件并让我有机会为特定接口实现类型准备序列化程序)。它在非分布式系统中也可以正常工作,在该系统中,我必须在尝试反序列化该类型之前运行一个序列化方法。但是,在分布式系统中的反序列化过程中,当前节点以前从未见过 Foo,ProtoBuf.Serializer 在运行 Foo.OnDeserializing 事件之前会抛出 InvalidOperationException 抱怨 Bar 类型缺少序列化程序(给我一个有机会告诉它如何反序列化 Bar)。
有没有办法附加一个钩子来确保我的代码有机会在 protobuf-net 抱怨缺少序列化程序之前了解“Foo”?
【问题讨论】:
标签: c# protobuf-net