C# 列表的协议缓冲区序列化
以下代码有什么问题C# 列表的协议缓冲区序列化,c#,.net,protobuf-net,C#,.net,Protobuf Net,以下代码有什么问题 MyList l = Serializer.DeepClone(new MyList { "abc" }); Console.WriteLine(l.Count == 1); 其中: [ProtoContract] public class MyList : List<String> { } [协议] 公共类MyList:列表 { } 期望值:真,实际值:假。我自己刚刚完成一个项目,在那里我正在使用Protobut,并在项目中使用了大约30个不同的Proto
MyList l = Serializer.DeepClone(new MyList { "abc" });
Console.WriteLine(l.Count == 1);
其中:
[ProtoContract]
public class MyList : List<String>
{
}
[协议]
公共类MyList:列表
{
}
期望值:真,实际值:假。我自己刚刚完成一个项目,在那里我正在使用Protobut,并在项目中使用了大约30个不同的ProtoContract,我只是回顾了一下,因为我认为我做了类似的工作,但事实上我从来没有直接做过这个特定的案例 所以我只是把它作为一个测试,但你可以把它用于你的目的。(是的,这是VB,但我现在比C快多了[但我已经做到了]) 结果不是我期望的,所以我把我的测试贴在这里。也许你可以用内部列表实现这个类(现在就让你完成) Mylist ProtoBuf False Mylist二进制格式化程序True Mylist2 ProtoBuf True MyListI ProtoBuf假 MyListThing ProtoBuf False
Imports System.IO
进口ProtoBuf
公开课入学
共享子主目录()
Dim l作为新的MyList
l、 添加(“abc”)
将新列表设置为MyList
使用ms作为新的内存流
序列化程序。序列化(MyList的)(ms,l)
ms.Seek(0,SeekOrigin.Begin)
newList=序列化程序。反序列化(MyList的)(ms)
终端使用
WriteLine(“Mylist ProtoBuf{0}”,newList.Count=1)
Dim f作为新的System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
使用ms作为新的内存流
f、 序列化(ms,l)
ms.Seek(0,SeekOrigin.Begin)
newList=CType(f.反序列化(ms),MyList)
终端使用
WriteLine(“Mylist二进制格式化程序{0}”,newList.Count=1)
Dim l2作为新MyList2
l2.项目。添加(“abc”)
将新列表2变暗为MyList2
使用ms作为新的内存流
序列化程序。序列化(MyList2)(ms,l2)
ms.Seek(0,SeekOrigin.Begin)
newList2=序列化程序。反序列化(MyList2的)(ms)
终端使用
WriteLine(“Mylist2 ProtoBuf{0}”,newList2.Items.Count=1)
朦胧的李作为新的MyListI
李.加(5)
我的名字叫Dim newListi
使用ms作为新的内存流
序列化程序。序列化(MyListI)(ms,li)
ms.Seek(0,SeekOrigin.Begin)
newListi=序列化程序。反序列化(MyListI的)(ms)
终端使用
WriteLine(“MyListI ProtoBuf{0}”,newListi.Count=1)
暗lh作为新的MyListThing
Add(newthing()和{.Message=“abc”})
朦胧的新感觉就像我的梦一样
使用ms作为新的内存流
序列化器。序列化(MyListThing)(ms,lh)
ms.Seek(0,SeekOrigin.Begin)
newListh=序列化程序。反序列化(MyListThing的)(ms)
终端使用
WriteLine(“MyListThing ProtoBuf{0}”,newListh.Count=1)
端接头
末级
公共类MyList
继承(字符串的)列表
末级
公共类MyList2
公共分新()
项目=新列表(字符串)
端接头
作为列表的公共属性项(字符串)
末级
公共类MyListI
继承(整数的)列表
末级
公共类物品
继承(事物的)列表
末级
公共类事物
作为字符串的公共属性消息
末级
如果您想要立即修复,只需拿走[ProtoContract]
;列表具有内置行为,不需要标记为合同
在这种情况下,合同定义优先于列表这一事实;我需要仔细观察,看看改变这一点是否会导致任何不必要的副作用
工作示例:
public class MyList : List<string>{}
[Test]
public void ListSubclassShouldRoundTrip()
{
var list = new MyList { "abc" };
var clone = Serializer.DeepClone(list);
Assert.AreEqual(1, clone.Count);
Assert.AreEqual("abc", clone[0]);
}
public类MyList:List{}
[测试]
public void list子类shouldldroundtrip()
{
var list=new MyList{“abc”};
var clone=Serializer.DeepClone(列表);
Assert.AreEqual(1,clone.Count);
Assert.AreEqual(“abc”,克隆[0]);
}
当前的示例:
[ProtoContract]
public class MyContractList : List<string> { }
[Test]
public void ContractListSubclassShouldRoundTrip()
{
var list = new MyContractList { "abc" };
var clone = Serializer.DeepClone(list);
Assert.AreEqual(1, clone.Count);
Assert.AreEqual("abc", clone[0]);
}
[协议]
公共类MyContractList:List{}
[测试]
public void ContractListSubclass应往返()
{
var list=新的MyContractList{“abc”};
var clone=Serializer.DeepClone(列表);
Assert.AreEqual(1,clone.Count);
Assert.AreEqual(“abc”,克隆[0]);
}
更新;然而,这看起来应该是可行的,因为当列表是某个类型的成员时,它可以正常工作;只有当列表是图形中最外层的类型时才会出现问题。示例(所有测试均通过):
[协议]
公共类ListWrapper
{
[原成员(1)]
公共列表基本列表{get;set;}
[原成员(2)]
公共MyList MyList{get;set;}
[原成员(3)]
公共MyContractList MyContractList{get;set;}
}
[测试]
public void TestBasicListAsMember()
{
var obj=newlistwrapper{BasicList=newlist{“abc”};
var clone=Serializer.DeepClone(obj);
Assert.IsNull(clone.MyList);
Assert.IsNull(clone.MyContractList);
aresequal(1,clone.BasicList.Count);
Assert.AreEqual(“abc”,克隆.BasicList[0]);
}
[测试]
public void testMyListMember()
{
var obj=newlistwrapper{MyList=newmylist{“abc”};
var clone=Serializer.DeepClone(obj);
Assert.IsNull(clone.BasicList);
Assert.IsNull(clone.MyContractList);
aresequal(1,clone.MyList.Count);
Assert.AreEqual(“abc”,clone.MyList[0]);
}
[测试]
public void TestMyContractListAsMember()
{
var obj=newlistwrapper{MyContractList=newmycontractlist{“abc”};
var clone=Serializer.DeepClone(obj);
Assert.IsNull(clone.BasicList);
Assert.IsNull(clone.MyList);
arenequal(1,clone.MyContractList.Count);
Assert.AreEqual(“abc”,clone.MyContractList[0]);
}
更新:这是一个微妙的bug,由列表的许多不同行为方式引起;对于具有getter和setter的成员列表,它的逻辑是“如果我们得到了列表,而它不是
[ProtoContract]
public class MyContractList : List<string> { }
[Test]
public void ContractListSubclassShouldRoundTrip()
{
var list = new MyContractList { "abc" };
var clone = Serializer.DeepClone(list);
Assert.AreEqual(1, clone.Count);
Assert.AreEqual("abc", clone[0]);
}
[ProtoContract]
public class ListWrapper
{
[ProtoMember(1)]
public List<string> BasicList { get; set; }
[ProtoMember(2)]
public MyList MyList { get; set; }
[ProtoMember(3)]
public MyContractList MyContractList { get; set; }
}
[Test]
public void TestBasicListAsMember()
{
var obj = new ListWrapper { BasicList = new List<string> { "abc" } };
var clone = Serializer.DeepClone(obj);
Assert.IsNull(clone.MyList);
Assert.IsNull(clone.MyContractList);
Assert.AreEqual(1, clone.BasicList.Count);
Assert.AreEqual("abc", clone.BasicList[0]);
}
[Test]
public void TestMyListAsMember()
{
var obj = new ListWrapper { MyList = new MyList { "abc" } };
var clone = Serializer.DeepClone(obj);
Assert.IsNull(clone.BasicList);
Assert.IsNull(clone.MyContractList);
Assert.AreEqual(1, clone.MyList.Count);
Assert.AreEqual("abc", clone.MyList[0]);
}
[Test]
public void TestMyContractListAsMember()
{
var obj = new ListWrapper { MyContractList = new MyContractList { "abc" } };
var clone = Serializer.DeepClone(obj);
Assert.IsNull(clone.BasicList);
Assert.IsNull(clone.MyList);
Assert.AreEqual(1, clone.MyContractList.Count);
Assert.AreEqual("abc", clone.MyContractList[0]);
}