使用protobuf-net序列化继承的类 [英] Serialize inherited classes using protobuf-net

查看:98
本文介绍了使用protobuf-net序列化继承的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用protobuf-net序列化派生类时遇到问题.我不知道是否是因为不支持它,或者我做错了事.

I have a problem serializing derived classes using protobuf-net. I don't know if it is because it is not supported, or I am doing something wrong.

我有一个通用基类(可以直接序列化),然后对此进行了专门化,但是我不能序列化.以下是这两个类的代码以及用法示例.我做错什么了吗?

I have a generic base class (which I can serialize directly) and then i make a specialization of this, but this one I can't serialize. The following is the code for the two classes and a example of usage. Am i doing something wrong?

修改

对通用类型增加了限制

基础

[ProtoBuf.ProtoContract]
public class Base<TKey, TValue>
    where TKey : Key
    where TValue : Key
{
    [ProtoBuf.ProtoMember(1)]
    public Dictionary<TKey, Dictionary<TKey, TValue>> Data { get; set; }
    [ProtoBuf.ProtoMember(2)]
    public TValue DefaultValue { get; set; }

    public Base()
    {
        this.Data = new Dictionary<TKey, Dictionary<TKey, TValue>>();
    }

    public Base(TValue defaultValue)
        : this()
    {
        this.DefaultValue = defaultValue;
    }

    public TValue this[TKey x, TKey y]
    {
        get
        {
            try { return this.Data[x][y]; }
            catch { return this.DefaultValue; }
        }
        set
        {
            if (!this.Data.ContainsKey(x))
                this.Data.Add(x, new Dictionary<TKey, TValue> { { y, value } });
            else
                this.Data[x][y] = value;
        }
    }
}

密钥类

public abstract class Key
{
}

专业密钥

[ProtoBuf.ProtoContract]
public class IntKey : Key
{
    [ProtoBuf.ProtoMember(1)]
    public int Value { get; set; }

    public IntKey() { }

    public override int GetHashCode()
    {
        return this.Value.GetHashCode();
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(obj, null)) return false;
        if (ReferenceEquals(obj, this)) return true;

        var s = obj as IntKey;
        return this.Value.Equals(s.Value);
    }
}

专业课

[ProtoBuf.ProtoContract]
public class IntWrapper<TKey> : Base<TKey, IntKey>
    where TKey : Key
{
    public IntWrapper()
        : base() { }

    public IntWrapper(IntKey defaultValue)
        : base(defaultValue) { }
}

用法示例

var path = @"C:\Temp\data.dat";
var data = new IntWrapper<IntKey>(new IntKey { Value = 0 }); // This will not be serialized
for(var x = 0; x < 10; x++)
{
    for(var y = 0; y < 10; y++)
        data[new IntKey { Value = x }, new IntKey { Value = y }] = new IntKey { Value = x + y };
}

using (var fileStream = new FileStream(path, FileMode.Create))
{
    ProtoBuf.Serializer.Serialize(fileStream, data);
}

推荐答案

模型需要按原语理解 基本类型和子类型之间的关系,尤其是用于唯一识别它.通常,这可以使用基本类型上的属性来完成,但是在使用泛型时会出现问题,因为您不能在属性中使用typeof(SomeType<TKey>).不过,您可以 在运行时定义它:

The model needs to understand in proto terms the relationship between base-type and sub-type, in particular the field used to uniquely identify it. Usually this would be done with attributes on the base type, but this is problematic when using generics, because you can't use typeof(SomeType<TKey>) in an attribute. You can define this at runtime, though:

RuntimeTypeModel.Default.Add(typeof (Base<int,int>), true)
              .AddSubType(3, typeof (IntWrapper<int>));

之后,它就可以工作了.

After that, it works.

这篇关于使用protobuf-net序列化继承的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆