簡體   English   中英

Protobuf繼承和泛型

[英]Protobuf Inheritance and Generics

我試圖使用ProtoBuf net來序列化具有以下格式的類的對象樹:

[ProtoContract]
class MySpecialCollectionList<T> : List<MySpecialCollection<T>>
{
    [ProtoMember(1)]
    public string Name { get; set; }
}

[ProtoContract]
class MySpecialCollection<T> : List<Special<T>>
{
    [ProtoMember(1)]
    public string Name { get; set; }
}

[ProtoContract]
class Special<T>
{
    [ProtoMember(1)]
    public string Name { get; set; }
    [ProtoMember(2)]
    public string Description { get; set; }

    [ProtoMember(3)]
    private readonly T _source; 
    T Source { get { return _source; } }

    private Special()
    {
    }

    public Special(T source) 
    { 
        _source = source; 
    }
}

interface IBeast
{
    string Name { get; set; }
}
[ProtoContract]
class Ant : IBeast
{
    [ProtoMember(1)]
    public string Name { get; set; }
}
[ProtoContract]
class Cat : IBeast
{
    [ProtoMember(1)]
    public string Name { get; set; }
}
[ProtoContract]
class Dog : IBeast
{
    [ProtoMember(1)]
    public string Name { get; set; }
}

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        MySpecialCollectionList<IBeast> collectionList = GetSpecialCollectionList();
        using (var fs = File.Create(@"c:\temp\protobuftest.bin"))
        {
            Serializer.Serialize(fs, collectionList);

            fs.Close();
        }
    }

    private MySpecialCollectionList<IBeast> GetSpecialCollectionList()
    {
        var ant = new Ant() { Name = "Mr Ant" };
        var cat = new Cat() { Name = "Mr Cat" };
        var dog = new Dog() { Name = "Mr Dog" };

        var Special = new Special<IBeast>(ant);

        var specialCollection1 = new MySpecialCollection<IBeast>() {
            {new Special<IBeast>(ant)},
            {new Special<IBeast>(cat)},
            {new Special<IBeast>(dog)}
        };
        specialCollection1.Name = "Special Collection1";


        var specialCollection2 = new MySpecialCollection<IBeast>() {
            {new Special<IBeast>(ant)},
            {new Special<IBeast>(dog)}
        };
        specialCollection2.Name = "Special Collection2";

        var specialCollectionList = new MySpecialCollectionList<IBeast>() {
            specialCollection1, specialCollection2 };

        specialCollectionList.Name = "Special Collection List";
        return specialCollectionList;
    }
}

注意我序列化的類( MySpecialCollectionList<T> )是如何從List<SomeOtherClass<T>>派生的,而不僅僅是List<T>

我正在努力找出在哪里放置“ProtoInclude”屬性來獲取它來序列化MySpecialCollectionList中的所有項目。 任何幫助將非常感激。

繼承在這里不是問題,因為即使A : BFoo<A> : Foo<B>也不是這樣。 請注意,protobuf-net不會使用非默認構造函數,盡管可以跳過構造函數,直接綁定到字段(甚至readonly )。 雖然你可能有6 T ,但是我無法看到(從代碼中)你懷疑哪種封閉類型會被懷疑,如果已知封閉類型你應該被設置。

如果你有一個Foo<SomeBaseClass>和從SomeBaseClass繼承的一些具體類型,那么標記將在SomeBaseClass

但是,如果您有一個具體的場景我可以用來重現您的問題,我很樂意看一看。


更新了重新編輯:

該示例中提出了幾個關鍵點:

  • 與大多數結合的API常見,XmlSerializer的和IIRC DataContractSerializer的,一個項目可以是一個列表與異或值的項目; 如果集合(實現IList東西)本身具有屬性,它們將不會被序列化; 封裝比這里的繼承更受歡迎,即具有 Name具有列表的東西(而不是具有 Name並且列表)
  • protobuf-net v1不支持基於接口的序列化; v2 可以 ,但是與XmlSerializer和DataContractSerializer一樣,你需要明確告訴它需要什么東西; 但很好,我們可以將[ProtoMember]移動到界面本身

這是v2中完全正常運行的版本:

using System.Collections.Generic;
using ProtoBuf;
[ProtoContract]
class MySpecialCollectionList<T>
{
    [ProtoMember(1)]
    public string Name { get; set; }

    private readonly List<MySpecialCollection<T>> items = new List<MySpecialCollection<T>>();
    [ProtoMember(2)]
    public List<MySpecialCollection<T>> Items { get { return items; } }
}

[ProtoContract]
class MySpecialCollection<T>
{
    [ProtoMember(1)]
    public string Name { get; set; }

    private readonly List<Special<T>> items = new List<Special<T>>();
    [ProtoMember(2)]
    public List<Special<T>> Items { get { return items; } }
}

[ProtoContract]
class Special<T>
{
    [ProtoMember(1)]
    public string Name { get; set; }
    [ProtoMember(2)]
    public string Description { get; set; }

    [ProtoMember(3)]
    private readonly T _source;
    T Source { get { return _source; } }

    private Special()
    {
    }

    public Special(T source)
    {
        _source = source;
    }
}
[ProtoContract]
[ProtoInclude(2, typeof(Ant))]
[ProtoInclude(3, typeof(Cat))]
[ProtoInclude(4, typeof(Dog))]
interface IBeast
{
    [ProtoMember(1)]
    string Name { get; set; }
}
[ProtoContract]
class Ant : IBeast
{
    public string Name { get; set; }
}
[ProtoContract]
class Cat : IBeast
{
    public string Name { get; set; }
}
[ProtoContract]
class Dog : IBeast
{
    public string Name { get; set; }
}

public static class Form1
{

    private static void Main()
    {
        MySpecialCollectionList<IBeast> collectionList = GetSpecialCollectionList();
        var copy = Serializer.DeepClone(collectionList);
    }

    private static MySpecialCollectionList<IBeast> GetSpecialCollectionList()
    {
        var ant = new Ant() { Name = "Mr Ant" };
        var cat = new Cat() { Name = "Mr Cat" };
        var dog = new Dog() { Name = "Mr Dog" };

        var Special = new Special<IBeast>(ant);

        var specialCollection1 = new MySpecialCollection<IBeast>() {Items =
            {new Special<IBeast>(ant),
            new Special<IBeast>(cat),
            new Special<IBeast>(dog)}
        };
        specialCollection1.Name = "Special Collection1";


        var specialCollection2 = new MySpecialCollection<IBeast>()
        {
            Items =
            {new Special<IBeast>(ant),
            new Special<IBeast>(dog)}
        };
        specialCollection2.Name = "Special Collection2";

        var specialCollectionList = new MySpecialCollectionList<IBeast>()
        {
            Items ={
            specialCollection1, specialCollection2 }
        };

        specialCollectionList.Name = "Special Collection List";
        return specialCollectionList;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM