如何在protobuf / C#中定义和反序列化IPAddress?

问题描述

innerHTML

还有outerHTML

public class Example
{
    public DateTime Date { get; set; }
    public IPAddress Ip { get; set; }
    public string ExampleDescription { get; set; }
}

我想使用Protobuf通过UDP从客户端服务器上发送上述示例消息,我不确定如何正确处理IPAddress。我可以将其序列化为字符串(这可能会改善与其他语言的互操作性),但我也看到过类似的.proto

Syntax = "proto3";
package example;

import "google/protobuf/timestamp.proto";

message Register {
    google.protobuf.Timestamp Date = 1;
    ??? Ip = 2;
    string ExampleDescription = 3;
}

我希望保持我的类(“示例”之上)完整无缺。我还需要同时支持IPv4和IPv6。我更喜欢小的,最佳的消息和反序列化,因为我正在处理数千p / sec,并且我希望这个数字将来会增加

无论哪种方式((解串)为字符串或使用.proto方法),我都需要为此实现自己的自定义(解串)器?最好的方法是什么,或者有人能找到有关如何在C#中实现此目标的良好教程/文档的指针吗?

将来,我可能还要使用oneof ip_addr { fixed32 v4 = 1; bytes v6 = 2; } ;我可能会重复使用“ ip proto”并在其上贴上oneof

解决方法

编辑:v3中增加了API,现在有3种不同的方法可以实现此目的;它们都记录在here中。


  • 如果您使用的是Google序列化程序;只是行不通-您需要使用protobuf原语的专用POCO进行序列化-大概是string
  • 如果您使用protobuf-net,则AllowParseableTypes是您的朋友;参见this example。我也将其粘贴在此处,以便您轻松查找。
using ProtoBuf.Meta;
using System;
using System.Net;
using Xunit;
using Xunit.Abstractions;

namespace ProtoBuf.Issues
{
    public class SO64101495
    {
        public SO64101495(ITestOutputHelper log)
            => Log = log;
        private readonly ITestOutputHelper Log;
        [Fact]
        public void RoundTripIPAddess()
        {
            var model = RuntimeTypeModel.Create();
            model.AllowParseableTypes = true;

            var schema = model.GetSchema(typeof(Example));
            Log?.WriteLine(schema);
            Assert.Equal(@"syntax = ""proto3"";
package ProtoBuf.Issues;
import ""google/protobuf/timestamp.proto"";
message Example {
   .google.protobuf.Timestamp Date = 1;
   string Ip = 2;
   string ExampleDescription = 3;
}
",schema);
        }



        [ProtoContract]
        [CompatibilityLevel(CompatibilityLevel.Level300)] // use timestamp.proto for Date
        public class Example
        {
            [ProtoMember(1)]
            public DateTime Date { get; set; }
            [ProtoMember(2)]
            public IPAddress Ip { get; set; }
            [ProtoMember(3)]
            public string ExampleDescription { get; set; }
        }
    }
}

Ver3中还有即将进行的更改,这应该使它更具扩展性。
这项新功能可能可以与您的oneof ip_addr方法配合使用,但需要一个虚拟包装器类型。如果您感兴趣,我可以进一步扩展这个想法。