C#-Protobuf.NET并列出对象的已知子类型:无法添加System.String?
作者:互联网
我正在尝试为如下所示的类编写序列化代码:
public class EventMessage
{
public Dictionary<string, object> Headers { get; set; }
public object Body { get; set; }
}
此类中的“对象”类型成员从很小的类型(基本上限于一种装配基本CLR类型)中保存对象.所以我想我可以简单地将这些类列出为对象类的子类型,如下所示:
model.Add(typeof(object), false)
.AddSubType(1, typeof(X))
.AddSubType(2, typeof(Y))
....
这样,我不必将类型信息嵌入到序列化的消息中,因为对象类的反序列化本身就像switch语句一样工作-它检查消息中存在哪个标签并将其反序列化为适当的类型.我喜欢这样,因为这样我就可以自由地重命名类,并在程序集中移动它们而不会造成任何破坏.
在开始测试标题(其中大多数包含字符串数据)之前,这在我的测试中效果很好.由于出现此异常,我无法将字符串标记为对象的子类型:
Data of this type has inbuilt behaviour, and cannot be added to a model in this way: System.String
有什么办法可以实现此行为,还是必须将类型信息嵌入消息中才能序列化此类?
解决方法:
protobuf-net存储结构化数据; object本质上不是结构化的,它不会让您简单地声明object的子类,也不会让您胡乱使用基本类型(例如string),该类型具有非常特殊的序列化规则.
This worked great in my tests
如果确实如此,那是一个错误;没有办法应该起作用.完全没有当然,这不是受支持的方案,也不能保证做正确的事(它也可能会严重破坏事情).在这种情况下,我将更改代码以显式导致异常.我要添加以下内容,以便尽快解决:
嗯….虽然这是一个无效的场景,但是我的回归测试强调这有一些“先验技术”,特别是:Why string interning on serialization in protobuf-net does not work in this example?
(这就是为什么每次我回答一个简单的protobuf-net问题时,我都会将其添加为回归测试,所以我没有说谎)
我想我不应该排除它,但是请考虑一下小猫:那不是我推荐的方法.我想我现在无法杀死它.但是,重点是:我无法启用此功能以将字符串(等)添加为子类型.仅考虑该API消息类型,即您的自定义类/结构.
This way I don’t have to embed type information into the serialized message since the deserialization of the object class itself works much like a switch statement
protobuf-net通常也不嵌入类型信息; p尽管有一些“动态”支持确实包括类型信息,但是在这种情况下并不需要.
在不嵌入任何类型信息的情况下,支持此操作的方法是封装所需的值,例如:
[TestFixture]
public class SO11641262
{
[Test]
public void Execute()
{
var model = TypeModel.Create();
model.Add(typeof (FooData), true)
.AddSubType(1, typeof (FooData<string>))
.AddSubType(2, typeof (FooData<int>))
.AddSubType(3, typeof (FooData<SomeOtherType>));
var val = FooData.Create("abc");
var clone = (FooData)model.DeepClone(val);
Assert.AreEqual("abc", clone.ValueUntyped);
Assert.AreEqual(typeof(string), clone.ItemType);
}
[ProtoContract]
public abstract class FooData
{
public static FooData<T> Create<T>(T value)
{
return new FooData<T> {Value = value};
}
public abstract Type ItemType { get; }
public abstract object ValueUntyped { get; set; }
}
[ProtoContract]
public class FooData<T> : FooData
{
[ProtoMember(1)]
public T Value { get; set; }
public override Type ItemType
{
get { return typeof (T); }
}
public override object ValueUntyped
{
get { return Value; }
set { Value = (T) value; }
}
}
[ProtoContract]
public class SomeOtherType {}
}
标签:protobuf-net,c 来源: https://codeday.me/bug/20191101/1980692.html