C# protobuf net使用字符串类型作为代理
我试图将一个C#类序列化为protobuf格式,该类的属性是特定于域的类型。但是这些类型应该作为值类型处理 我正在使用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
[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的示例编辑了我的问题。