C# protobuf net使用字符串类型作为代理

C# protobuf net使用字符串类型作为代理,c#,serialization,protocol-buffers,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 DomainTypeToBeHandldedAsStri

我试图将一个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));
但这一方法失败了,只有一个例外:

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);
syntax = "proto3";
package ProtoBufferSerializerTest;

message TestClass {
   string StringProperty = 1;
   repeated int32 DomainTypeToBeHandldedAsInt = 2 [packed = false];
}
这就产生了这样一个.proto文件:

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

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

但是我不想重复这一点,我也不需要[packed=false]这个问题。

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

基本上,它查找
公共静态{Type}解析(字符串)
模式。但是:我同意最好明确地表达这一点,“代理字符串”是一种很好的表达方式。我愿意为问题中的内容添加直接支持,但现在还没有,需要一些代码更改。可能不太多,因为功能的基本要素已经通过可解析类型存在了

下面是一个示例中的可解析类型方法,该方法现在应该可以使用:

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);
    }
}

谢谢你,马克。。。我自己找到了AllowParseableTypes选项,但因为我也想支持int、decimal等,所以它并不能解决我所有的问题。将代理项定义为字符串也比较简单,因为我不必在我的DomainTypeToBeHandldedAsString上引入这两个新方法。我现在没有太多的空闲时间,但如果我发现了一些,那么你能告诉我在你的代码中我必须去哪里实现它吗?然后我会很高兴地写一个pull请求。目前我的时间非常有限,所以不要等我,但如果可以的话,我愿意帮忙。我几乎按照自己的意愿完成了工作。我没有设置代理,而是在DomainTypeToBeHandldedAsInt上实现了IConvertible,并添加了如下属性:model[typeof(TestClass)];但这产生了这样的结果:重复int32 DomainTypeTobehandledasint=1[packed=false];不完全是我想要的,但很接近。该类型实际上没有重复,我也不知道packed=false是什么意思。@JayPete我需要查看更多的上下文来对其进行评论,我用一个我尝试使用IConvertible的示例编辑了我的问题。