protobuf-net 反序列化而不提供输出类型 [英] protobuf-net deserialization without providing out type

查看:40
本文介绍了protobuf-net 反序列化而不提供输出类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么不提供输出类型就不能反序列化?

Why is not possible to Deserialize without providing output type?

通常,如果两个端点正在通信,则两端共享相同的类型.就我而言,我在客户端和服务器应用程序上使用完全相同的库.启动时,我在客户端和服务器上注册所有类型,如下所示:

Typically if two endpoints are communicating, both ends are sharing the same types. In my case i'm using exactly the same library on the client and on the server application. On startup i register all my types both on client and server like this:

 var metaType = RuntimeTypeModel.Default.Add( type, false );
 foreach( var prop in type.GetProperties() )
     metaType.Add( i++, prop.Name );

所以我希望 protobuf 尝试理解它应该反序列化为什么而不提供类型.目前我正在使用它来反序列化:

and so i expect protobuf to try to understand what it should deserialize into without providing a type. At the moment i'm using this to deserialize:

RuntimeTypeModel.Default.DeserializeWithLengthPrefix(
    stream, null, type, ProtoBuf.PrefixStyle.Fixed32, 0 );

这种行为(也可以在其他序列化器中找到)迫使我拥有一个超类型来包装我想要序列化的每个对象,并且在其中我有实际的有效载荷和一些其他信息,可以帮助我了解如何反序列化有效载荷.所以我可以写这样的东西:

This kind of behaviour (found in other serializer too) forces me to have a supertype that wraps every object i want to serialize and within which i have actual payload and some other info that help me understand how to deserialize the payload. So i can write something like this:

public class MySuperType
{
    public byte[] Payload {get; set;}
    public Type PayloadType {get; set;} 
}

public object Deserialize( byte[] bytes )
{
    using( var stream = new MemoryStream( bytes ) )
    {
        var wrapperObject = Serializer.DeserializeWithLengthPrefix<MySupertype>
           ( stream, ProtoBuf.PrefixStyle.Fixed32 );

        using( var stream = new MemoryStream( wrapperObject.Payload ) )
        {
             var actualPayloadObject = RuntimeTypeModel.Default.DeserializeWithLengthPrefix(
                 stream, null, wrapperObject.PayloadType, ProtoBuf.PrefixStyle.Fixed32, 0 );

             return actualPayloadObject;
        }
    }    
}

所以我基本上知道我收到的每个对象都是 MySupertype 类型.我把事情复杂化了吗?

So I basically know every object i receive is of type MySupertype. Am i complicating things out?

推荐答案

protobuf 流指示根数据类型是不正常的.期望调用代码知道数据是什么样的.但是,还有其他方法可以解决该主题.例如,一种常见的方法是为每个类型指定一个标签编号,并使用稍微复杂的序列化/反序列化重载来执行此查找 - 但是,这仍然需要代码来配置数字/类型之间的映射.

It is not normal for a protobuf stream to indicate the root data type. It is expected that the calling code knows what the data looks like. However, there are other ways to approach the topic; for example, a common approach is to designate a tag number per type and use a slightly more complicated serialize / deserialize overload that performs this lookup - however, this still requires the code to configure the mapping between numbers / types.

有时更方便的方法通常是使用继承:

A sometimes-more-convenient approach is often to use inheritance:

[ProtoContract]
[ProtoInclude(1, typeof(FooRequest))]
[ProtoInclude(2, typeof(BarRequest))]
public class RequestBase {}

public class FooRequest : RequestBase {...}
public class BarRequest : RequestBase {...}

这也避免了对 Type 进行序列化的需要,这在 IMO 不是一个好主意,并且会在版本控制时导致问题.有了上面的内容,您可以始终使用 RequestBase - 可能对有趣的代码使用多态(virtualabstract 方法).

This also avoids the need for Type to be serialized, which is IMO not a good idea and can cause problems when versioning. With the above, you can use RequestBase throughout - perhaps using polymorphism (virtual or abstract methods) for the interesting code.

这篇关于protobuf-net 反序列化而不提供输出类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆