2011-05-26 129 views
1

考慮下面的代碼:protobuf的,繼承和泛型

[Serializable, ProtoContract] 
[ProtoInclude(100, typeof(ValueA))] 
[ProtoInclude(101, typeof(ValueB))] 
public class Value 
{ 
} 

[Serializable, ProtoContract] 
public class ValueA : Value 
{ 
} 

[Serializable, ProtoContract] 
public class ValueB : Value 
{ 
} 

[Serializable, ProtoContract] 
[ProtoInclude(1000, typeof(ContainerA))] 
[ProtoInclude(1001, typeof(ContainerB))] 
public class Container<T> where T : Value 
{ 
    [ProtoMember(1)] 
    public T Item; 
} 

[Serializable, ProtoContract] 
public class ContainerA : Container<ValueA> 
{ 
} 

[Serializable, ProtoContract] 
public class ContainerB : Container<ValueB> 
{ 
} 

我得到試圖序列ContainerA/ContainerB時出現錯誤:

ProtoBuf.ProtoException:已知類型的 ContainerB爲ProtoIncludeAttribute 必須是 的直接子類容器`1

Comme nting出以下行之一 - 因此,只有一個類從容器繼承 - 將使protobuf的重新快樂起來:

[ProtoInclude(1000, typeof(ContainerA))] 
[ProtoInclude(1001, typeof(ContainerB))] 

這是怎麼回事就在這裏的什麼辦法做些什麼?

TIA

+0

哪個protobuf的版本網是那個btw?只是想知道爲什麼這個消息有點詭異...... – 2011-05-26 17:15:13

+0

封閉泛型類型並非真正直接從它們的* open *泛型定義繼承而來 - 它更復雜一些。你能澄清你試圖建模什麼嗎?還是代碼說明了這一切? – 2011-05-26 17:21:40

+0

嗨馬克!代碼準確地說明了我遇到的問題,但爲了理解「現實」中發生了什麼,我應該寫下「公開列表項目」;而不僅僅是「公共T項目」; (儘管在真正的代碼中我們還有一個繼承級別)。所以我們正在建模不同類型的「時間序列」,在那裏我們可以有一些不同類型的「時間序列值」 - 如果這使得更清晰? – 2011-05-27 06:25:35

回答

1

我仍然在等待更多的信息,但最終從開放泛型類型繼承是有點棘手。也許,如果我知道確切的型號,我可以添加更多的,但下面的工作:

using System.Diagnostics; 
using ProtoBuf; 
[ProtoContract] 
[ProtoInclude(1, typeof(ValueA))] 
[ProtoInclude(2, typeof(ValueB))] 
public class Value 
{ 
} 

[ProtoContract] 
public class ValueA : Value 
{ 
} 

[ProtoContract] 
public class ValueB : Value 
{ 
} 
[ProtoContract] 
[ProtoInclude(1, typeof(Container<ValueA>))] 
[ProtoInclude(2, typeof(Container<ValueB>))] 
public abstract class Container 
{ 

    public abstract Value BaseValue { get; set; } 
} 
[ProtoContract] 
public class Container<T> : Container where T : Value 
{ 
    [ProtoMember(1)] 
    public T Value { get; set;} 

    public override Value BaseValue 
    { 
     get { return Value; } 
     set { Value = (T)value; } 
    } 
} 

static class Program 
{ 
    static void Main() 
    { 
     var model = new Container<ValueA>(); 
     model.Value = new ValueA(); 
     var clone = Serializer.DeepClone(model); 
     Debug.Assert(clone.Value is ValueA); 
    } 
} 

雖然實際上ValueAValueB之間的關係是完全不必要的,除非你需要它:

using System.Diagnostics; 
using ProtoBuf; 

[ProtoContract] 
public class ValueA 
{ 
} 

[ProtoContract] 
public class ValueB 
{ 
} 

[ProtoContract] 
[ProtoInclude(1, typeof(Container<ValueA>))] 
[ProtoInclude(2, typeof(Container<ValueB>))] 
public abstract class Container 
{ 

    public abstract object BaseValue { get; set; } 
} 
[ProtoContract] 
public class Container<T> : Container 
{ 
    [ProtoMember(1)] 
    public T Value { get; set;} 

    public override object BaseValue 
    { 
     get { return Value; } 
     set { Value = (T)value; } 
    } 
} 

static class Program 
{ 
    static void Main() 
    { 
     var model = new Container<ValueA>(); 
     model.Value = new ValueA(); 
     var clone = Serializer.DeepClone(model); 
     Debug.Assert(clone.Value is ValueA); 
    } 
} 
+0

Marc,自回覆日期以來有所改變?在層次結尾的封閉泛型通常是有用的,但似乎它仍然沒有與ProtoBuf.net序列化 - 雖然沒有像原始問題那樣的錯誤,但我仍然在公共T值{get;設置;}從容器。 – ProfyTroll 2014-04-22 21:14:46