[英]Protobuf Inheritance and Generics
I am attempting to use ProtoBuf net to serialize an object tree with the classes in the following format: 我试图使用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;
}
}
Notice how the class I am serializing ( MySpecialCollectionList<T>
) is derived from a List<SomeOtherClass<T>>
, not just List<T>
. 注意我序列化的类( MySpecialCollectionList<T>
)是如何从List<SomeOtherClass<T>>
派生的,而不仅仅是List<T>
。
I am struggling to work out where to put "ProtoInclude" attributes to get this to serialize all the items in the MySpecialCollectionList. 我正在努力找出在哪里放置“ProtoInclude”属性来获取它来序列化MySpecialCollectionList中的所有项目。 Any help would be much appreciated. 任何帮助将非常感激。
Inheritance is not an issue here since even if A : B
it is not true that Foo<A> : Foo<B>
. 继承在这里不是问题,因为即使A : B
, Foo<A> : Foo<B>
也不是这样。 Note that protobuf-net won't use a non-default constructor, although it is possible to skip the constructor, binding to the field directly (even readonly
). 请注意,protobuf-net不会使用非默认构造函数,尽管可以跳过构造函数,直接绑定到字段(甚至readonly
)。 While you may have 6 T
, I can't see (from the code) that it would ever be in doubt which closed type you intend, and if the closed type is known you should be set. 虽然你可能有6 T
,但是我无法看到(从代码中)你怀疑哪种封闭类型会被怀疑,如果已知封闭类型你应该被设置。
If you have a Foo<SomeBaseClass>
and a number of concrete types inherited from SomeBaseClass
then the markers would o on SomeBaseClass
. 如果你有一个Foo<SomeBaseClass>
和从SomeBaseClass
继承的一些具体类型,那么标记将在SomeBaseClass
。
However, if you have a concrete scenario I can use to reproduce your issue, I'll happily take a look. 但是,如果您有一个具体的场景我可以用来重现您的问题,我很乐意看一看。
Updated re edit: 更新了重新编辑:
There are a couple of key points drawn out in the example: 该示例中提出了几个关键点:
IList
) has properties itself, they will not be serialized; 如果集合(实现IList
东西)本身具有属性,它们将不会被序列化; encapsulation is preferred over inheritance here, ie something that has a Name
and has a list (rather than has a Name
and is a list) 封装比这里的继承更受欢迎,即具有 Name
并具有列表的东西(而不是具有 Name
并且是列表) [ProtoMember]
onto the interface itself 但很好,我们可以将[ProtoMember]
移动到界面本身 Here's a fully working version in v2: 这是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.