c# - protobuf-net 使用字符串类型作为代理项

标签 c# serialization protocol-buffers protobuf-net

我正在尝试将一个 C# 类序列化为 protobuf 格式,该类具有域特定类型的属性。但是这些类型应该作为值类型来处理。

我正在使用 protobuf.net。

这是一个例子

[ProtoContract]
public class TestClass
{
    [ProtoMember(1)]
    public string StringProperty { get; set; }

    [ProtoMember(2)]
    public DomainTypeToBeHandldedAsString DomainTypeToBeHandldedAsString { get; set; }
}

public class DomainTypeToBeHandldedAsString
{
    public string Value { get; set; }

    public static implicit operator string(DomainTypeToBeHandldedAsString domainType)
    {
        return domainType?.Value;
    }

    public static implicit operator DomainTypeToBeHandldedAsString(string s)
    {
        return new DomainTypeToBeHandldedAsString {Value = s};
    }
}

在序列化消息中,我不希望人们关心 DomainTypeToBeHandldedAsString。我只是想让他们看到一个字符串并发送一个字符串。

所以我尝试这样做:

var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model.Add(typeof(DomainTypeToBeHandldedAsString), false).SetSurrogate(typeof(string));

但这失败了,出现了这个异常(exception):

System.ArgumentException: 'Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be used as a surrogate'

有没有办法为这样的类指定自定义序列化程序?而且应该说还有域类型应该被当作int或者其他值类型来对待。所以不仅仅是字符串。

谢谢

编辑

我还尝试了这个:

[ProtoContract]
public class TestClass
{
    [ProtoMember(1)]
    public string StringProperty { get; set; }

    public DomainTypeToBeHandldedAsInt DomainTypeToBeHandldedAsInt { get; set; }
}

[ProtoContract]
public class DomainTypeToBeHandldedAsInt : IConvertible
{
    [ProtoMember(1)]
    public int Value { get; set; }

    public static implicit operator int(DomainTypeToBeHandldedAsInt domainType)
    {
        return domainType?.Value ?? 0;
    }

    public static implicit operator DomainTypeToBeHandldedAsInt(int s)
    {
        return new DomainTypeToBeHandldedAsInt { Value = s };
    }

    public int ToInt32(IFormatProvider provider)
    {
        return Value;
    }

    //All the rest throw a NotImplementedException
}

然后我将类型添加到 RunTimeModel,如下所示:

var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model[typeof(TestClass)].Add(2, "DomainTypeToBeHandldedAsInt", typeof(Int32), null);

这导致了一个像这样的 .proto 文件:

syntax = "proto3";
package ProtoBufferSerializerTest;

message TestClass {
   string StringProperty = 1;
   repeated int32 DomainTypeToBeHandldedAsInt = 2 [packed = false];
}

但我不想重复这个,我也不需要 [packed = false]。

最佳答案

这是一个非常有趣的问题。目前,答案是“不,不支持”,但是:支持以下如果您启用AllowParseableTypes (在 RuntimeTypeModel 实例上 - RuntimeTypeModel.DefaultSerializer.* 方法背后的实例):

public class DomainTypeToBeHandldedAsString
{
    public string Value { get; set; }
    public override string ToString() => Value;
    public static DomainTypeToBeHandldedAsString Parse(string s)
        => new DomainTypeToBeHandldedAsString { Value = s };
}

基本上,它会查找 public static {Type} Parse(string) 模式。但是:我同意明确表达这一点会更好,“代理项作为字符串”是表达这一点的好方法。我愿意为您在问题中所拥有的内容添加直接支持,但今天不存在,需要进行一些代码更改。可能不是很多,因为该功能的要素已经通过可解析类型存在!

下面是在今天应该有效的示例中使用的可解析类型方法:

using ProtoBuf;
using ProtoBuf.Meta;

public class DomainTypeToBeHandldedAsString
{
    public string Value { get; set; }
    public override string ToString() => Value;
    public static DomainTypeToBeHandldedAsString Parse(string s)
        => new DomainTypeToBeHandldedAsString { Value = s };
}
[ProtoContract]
public class Bar
{
    [ProtoMember(1)]
    public DomainTypeToBeHandldedAsString A { get; set; }
}
class Program
{
    static void Main()
    {
        RuntimeTypeModel.Default.AllowParseableTypes = true;
        var obj = new Bar { A = new DomainTypeToBeHandldedAsString { Value = "abcdef" } };
        var clone = Serializer.DeepClone(obj);
        System.Console.WriteLine(clone.A.Value);
    }
}

关于c# - protobuf-net 使用字符串类型作为代理项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45323448/

相关文章:

c# - 获取类型的转换器

c# - 如何使 DataGridView 中的第一行列不可单击?

c# - 反序列化压缩字符串时出错(解析完成前遇到流结束)C#

Java序列化

rest - 在 gRPC 之上对 REST web 服务进行版本控制

c# - 无法将类型 'string' 隐式转换为 'System.Windows.Forms.ColumnHeader

c# - 弹性嵌套将动态值传递给排序

ReSTLet 2.1-M4 以上版本的 Java 序列化问题

google-analytics - 如何解码谷歌 gclids

java - 如何解析Envelope.Payload.Data的protobuf数据?