c# - 使用 protobuf-net 动态反序列化基于类型变量的类

标签 c# udp protocol-buffers protobuf-net

我正在尝试创建一个标准化的事件消息传递系统(用于我的游戏服务器和客户端),该系统使用 protobuf-net 通过 UDP 套接字发送数据以实现快速和最佳的数据传输。

目前我正在尝试发送一个事件类,目前可以是 PlayerIntentEvent 类或 OnConnectionEvent 类(存在更多事件,那些是只是一个例子)。

我正在发送一个 byte[],其中第一个字节代表事件类(用于反序列化),byte[] 的其余部分是类本身,用 protobuf-net 序列化。这部分工作正常。我的问题在接收部分。 我想根据类型变量动态反序列化一个类。

经过一周的搜索和尝试不同的事情后,我找不到这样做的方法。

我当前的设置:

事件类型的常量:

public static class EventTypes {
    public static byte OnConnection = 1;
    public static byte OnError = 2;
    public static byte OnPlayerIntent = 3;
}

服务器的事件映射:

public static class Constants {

    public static Dictionary<byte, Type> EventDataCastDictionary = new Dictionary<byte, Type> {
        { EventTypes.OnConnection, null },
        { EventTypes.OnPlayerIntent, typeof (PlayerIntentEvent) }
    };

    public static readonly IPEndPoint ClientEndPoint = new IPEndPoint(IPAddress.Any, 0);

    public static readonly IPEndPoint ServerEndPoint = new IPEndPoint(IPAddress.Any, 9423);
}

出于测试目的,我创建了一个仅将 PlayerIntentEvents 发送到服务器的发送器方法:

public void SendPlayerIntent(PlayerIntentEvent packet) {
        try {
            byte[] bytes;
            using (MemoryStream stream = new MemoryStream()) {
                stream.WriteByte(EventTypes.OnPlayerIntent);
                ProtoBuf.Serializer.Serialize<PlayerIntentEvent>(stream, packet);
                bytes = stream.ToArray();
            }
            //client is an instance of UdpClient
            client.Send(bytes, bytes.Length, serverEndPoint);

        } catch (Exception err) {
            throw err;
        }
    }

我的服务器的接收方:

using System;
using System.IO;
using System.Net.Sockets;
using System.Threading.Tasks;
using ProtoBuf;

abstract class UdpBase {
    protected UdpClient Client;

    protected UdpBase() {
        Client = new UdpClient();
    }

    public async Task<Received> Receive() {
        var receivedStream = await Client.ReceiveAsync();
        NetworkPacket networkPacket = new NetworkPacket();

        object packet = null;
        //Getting the class type from the first byte of the array
        Type eventType = Constants.EventDataCastDictionary[receivedStream.Buffer[0]];

        //----PROBLEM
        //Here I am reading only the class
        using (var stream = new MemoryStream(receivedStream.Buffer, 1, receivedStream.Buffer.Length - 1)) {
        //I want to put a type from my mapping in place of the ?????*
        //I have tried using eventType variable, but the code does not compile
            packet = Serializer.Deserialize<?????*>(stream);
        }
        //----END OF PROBLEM    

        //The return statement is not finished
        return new Received();
    }
}

更新:

使用David修改后我开始收到

Exception thrown: 'ProtoBuf.ProtoException' in protobuf-net.dll
Exception thrown: 'ProtoBuf.ProtoException' in mscorlib.dll

更新 2:

我的事件类缺少默认的无参数构造函数。现在一切正常,即使没有 Convert.ChangeType。 :)

最佳答案

您可以使用 non-generic overload并转换结果:

Type eventType = Constants.EventDataCastDictionary[receivedStream.Buffer[0]];
using (var stream = new MemoryStream(receivedStream.Buffer, 1, 
        receivedStream.Buffer.Length - 1)) {
    packet =  Convert.ChangeType(Serializer.Deserialize(eventType, stream),
                                 eventType);
}

关于c# - 使用 protobuf-net 动态反序列化基于类型变量的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38551972/

相关文章:

c# - 您可以将 XUnit 测试标记为显式吗?

c# - 你如何在C#中用一个字符串拆分一个字符串

windows - 在 Windows 下更改默认套接字缓冲区大小

enums - 使用 protobuf 枚举值作为字段编号

c++ - 当我使用 Protocol Buffer 时,我怎么知道服务器端的 ByteSize()?

javascript - 协议(protocol) JSON (PSON) 与 Protocol Buffer

c# - 顺序引导生成器

c# - 在使用 Visual Studio 2010 时将调试器附加到程序时看不到托管变量名称

ffmpeg - UDP Receiver 需要在 udp sender 之前启动

node.js - Nodejs + Express : make http request wait for udp response