负载平衡系统中的Protobuf-net动态类型

时间:2018-08-09 19:10:22

标签: c# protobuf-net

我在一个应用程序中使用protobuf-net,该应用程序对来自(出于所有意图和目的)第三方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'吗?

1 个答案:

答案 0 :(得分:2)

我还没有尝试过这种情况,但是:为了提供一些灵活性,所有Type的存储和补液都通过TypeModel.DynamicTypeFormatting事件进行;因此,从理论上讲,您可以将事件挂在RuntimeTypeModel.Default上,例如:

RuntimeTypeModel.DynamicTypeFormatting += (sender, args) => {
    if (args.FormattedName != null) { // meaning: rehydrating
        lock(SomeSyncLock) {
            if(NotYetKnown(args.FormattedName))
                Prepare(args.FormattedName);
        }
    }
};

该API的意图允许您控制如何解析类型,但是...我想它也可以解决此问题?


但是,我可以支持在第一次看到新的Type时故意针对性更强的事件的想法,本质上是替换/补充了“应用默认行为”代码。不过,我认为它今天不存在。