编程语言
首页 > 编程语言> > C#-Protobuf.NET并列出对象的已知子类型:无法添加System.String?

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