Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在protobuf net中,是否可以基于基类型部分反序列化消息_C#_Protocol Buffers_Protobuf Net - Fatal编程技术网

C# 在protobuf net中,是否可以基于基类型部分反序列化消息

C# 在protobuf net中,是否可以基于基类型部分反序列化消息,c#,protocol-buffers,protobuf-net,C#,Protocol Buffers,Protobuf Net,在protobuf net中,是否可以基于基类型部分反序列化消息 在我的系统中,我有一个继承层次结构,其中每个消息都从MessageBase继承。MessageBase具有uint消息类型。理想情况下,我只想反序列化MessageBase并检查它是否是我感兴趣的消息类型,然后我可以扔掉消息或决定反序列化实际消息。这是为了节省反序列化的成本(我有一个cpu周期预算和大量的消息要处理) 示例用法如下所示 非常感谢 MessageBase msgBase = ..deserialize; i

在protobuf net中,是否可以基于基类型部分反序列化消息

在我的系统中,我有一个继承层次结构,其中每个消息都从MessageBase继承。MessageBase具有uint消息类型。理想情况下,我只想反序列化MessageBase并检查它是否是我感兴趣的消息类型,然后我可以扔掉消息或决定反序列化实际消息。这是为了节省反序列化的成本(我有一个cpu周期预算和大量的消息要处理)

示例用法如下所示

非常感谢

 MessageBase msgBase = ..deserialize; 

  if(msgBase.MessageType = 1)//1 is the Tick msg type
  {
     Tick tick = ..deserialize actual msg;
     //do something with tick
   }
  //throw away msgBase 

[ProtoContract,ProtoInclude(1, typeof(Tick))]
public class MessageBase
{
    protected uint _messageType;

    [ProtoMember(1)]
    public uint MessageType
    {
        get { return _messageType; }
        set{ _messageType = value;}
    }
}

[ProtoContract]
public public class Tick : MessageBase
{
    private int _tickId;
    private double _value;

    public Tick()
    {
        _messageType = 1;
    }

    [ProtoMember(1)]
    public int TickID
    {
        get { return _tickId; }
        set { _tickId = value; }
    }
    [ProtoMember(2)]
    public double Value
    {
        get { return _value; }
        set { _value = value; }
    }
}
如果它是消息的一部分,那么现在:不。因为它是字段1,我可能会预先筛选它们,但即使这是一个黑客攻击(不能保证字段1是第一个-规范明确指出,您必须允许任何订购)

然而

如果您愿意进行一些重构,可能会有一个选择。如果这是一个线性异构的消息序列,那么编码它的另一种方法是使用
SerializeWithLengthPrefix
实现,为每个消息类型传递不同的标记-然后您有一个类似的序列(表示有点自由)

当然,这有点取决于另一端的匹配,但除非我弄错了,否则这与类似SAX的处理(作为建议)有很好的关系,顺便说一句,这也完全符合非泛型反序列化的工作方式。下面是一个示例,仅对
对象进行反序列化,在控制台上显示“2”和“4”:

using System;
using System.IO;
using ProtoBuf;
[ProtoContract]
class Foo
{
    [ProtoMember(1)]
    public int A { get; set; }
}
[ProtoContract]
class Bar
{
    [ProtoMember(1)]
    public int B { get; set; }
}
static class Program
{
    static void Main()
    {
        using (var ms = new MemoryStream())
        {
            Serializer.SerializeWithLengthPrefix(ms, new Foo { A = 1 }, PrefixStyle.Base128, 1);
            Serializer.SerializeWithLengthPrefix(ms, new Bar { B = 2 }, PrefixStyle.Base128, 2);
            Serializer.SerializeWithLengthPrefix(ms, new Foo { A = 3 }, PrefixStyle.Base128, 1);
            Serializer.SerializeWithLengthPrefix(ms, new Bar { B = 4 }, PrefixStyle.Base128, 2);
            ms.Position = 0;

            // we want all the Bar - so we'll use a callback that says "Bar" for 2, else null (skip)
            object obj;
            while (Serializer.NonGeneric.TryDeserializeWithLengthPrefix(ms, PrefixStyle.Base128,
                tag => tag == 2 ? typeof(Bar) : null, out obj))
            {
                Console.WriteLine(((Bar)obj).B);
            }
        }
    }
}
在导线上,这实际上与父对象兼容:

repeated foo foo = 1;
repeated bar bar = 2;
如果建议的
选项generate_visitors
得到实现,您应该能够使用来自任何客户端的相同类型的异构数据流。显而易见的映射类似于
[ProtoContract]
上的可选属性来帮助实现这一点,但在新的protobuf功能明确之前,我不想添加它,因为到目前为止,它看起来与我的实现完全匹配。这很好

repeated foo foo = 1;
repeated bar bar = 2;