C# 使用protobuf net序列化继承的类

C# 使用protobuf net序列化继承的类,c#,inheritance,serialization,protobuf-net,C#,Inheritance,Serialization,Protobuf Net,我在使用protobuf net序列化派生类时遇到问题。我不知道是因为它不被支持,还是我做错了什么 我有一个泛型基类(我可以直接序列化),然后我对它进行专门化,但这个基类我不能序列化。下面是这两个类的代码和用法示例。我做错什么了吗 编辑 对泛型类型添加了限制 基础 [ProtoBuf.ProtoContract] public class Base<TKey, TValue> where TKey : Key where TValue : Key { [Pro

我在使用protobuf net序列化派生类时遇到问题。我不知道是因为它不被支持,还是我做错了什么

我有一个泛型基类(我可以直接序列化),然后我对它进行专门化,但这个基类我不能序列化。下面是这两个类的代码和用法示例。我做错什么了吗

编辑

对泛型类型添加了限制

基础

[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;
        }
    }
}
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);
}
专用键

[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);
    }
}
专业课

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

    public IntWrapper(IntKey defaultValue)
        : base(defaultValue) { }
}
[ProtoBuf.ProtoContract]
公共类IntWrapper:Base
其中TKey:Key
{
公共IntWrapper()
:base(){}
公共IntWrapper(IntKey defaultValue)
:base(defaultValue){}
}
用法示例

[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;
        }
    }
}
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);
}
var path=@“C:\Temp\data.dat”;
var data=newintwrapper(newintkey{Value=0});//这将不会被序列化
对于(变量x=0;x<10;x++)
{
对于(变量y=0;y<10;y++)
data[new IntKey{Value=x},new IntKey{Value=y}]=new IntKey{Value=x+y};
}
使用(var fileStream=newfilestream(路径,FileMode.Create))
{
序列化(文件流,数据);
}

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

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

在那之后,它就可以工作了。

好吧,如果我将泛型类型的范围限制为从某个抽象类继承(我将其添加到了Q中),该怎么办。因此,现在基础结构只允许类型为
Key
的类型,这会更容易吗?@aweis需要看一个具体的例子;但是:大多数常见的场景都可以用
[ProtoInclude(…)]
来处理。这个例子就是问题中的代码。我最大的问题是我无法控制给基类的类型,但我可以要求它们是可序列化的,所以我认为限制它们继承特定的基类也会限制范围@aweis protobuf net与XmlSerializer一样,喜欢提前知道结构。。。它不是为了序列化完全不可预测的typesOkay而设计的,那么我将进行一些重新设计。谢谢