.NET不能反序列化嵌套结构?我无法让C#(VS2008、CompactFramework、.NET是3.5SP1版)成功反序列化嵌套结构。当我在移动设备上的模拟器(我使用的是“PocketPC2003第二版”模拟器)上运行它时,问题只发生在CF中,在我的Windows机器上运行的完全相同的代码没有同样的问题。这是我的代码:publicstructFred{publicstringName;}publicstructMiddle{publicFred[]Freds;}publicstructTop{publicMiddleMiddle;公共弗雷德[]弗雷德斯;}publicstaticvoidTest(){Toptop=newTop();top.Middle.Freds=newFred[2];top.Middle.Freds[0].Name="Fred20";top.Middle.Freds[1].Name="Fred21";top.Freds=newFred[2];top.Freds[0].Name="Fred10";top.Freds[1].Name="Fred11";StringBuildersb=newStringBuilder();System.Xml.Serialization.XmlSerializerx=newSystem.Xml.Serialization.XmlSerializer(top.GetType());使用(StringWritersw=newStringWriter(sb)){x.Serialize(sw,top);}字符串xml=sb.ToString();string[]lines=xml.Split(newchar[]{'r','n'});foreach(stringlineinlines){Debug.WriteLine(""+line.Trim());}MemoryStreamms=newMemoryStream(System.Text.Encoding.ASCII.GetBytes(xml));StreamReadersr=newStreamReader(ms);对象o=x.Deserialize(sr);Debug.WriteLine("反序列化为"+o);Topgo2=(Top)o;if(go2.Freds==null)Debug.WriteLine("go2.Fredsisnull");elseDebug.WriteLine("go2.Freds[0].Nameis""+go2.Freds[0].Name+""");if(go2.Middle.Freds==null)Debug.WriteLine("go2.Middle.Fredsisnull");elseDebug.WriteLine("go2.Middle.Freds[0].Nameis""+go2.Middle.Freds[0].Name+""");当我运行它时,它创建的XML看起来不错:Fred20Fred21Fred10Fred11但C#无法成功反序列化此XML-控制台输出是这样的:DeserializedintoTopgo2.Freds[0].Nameis"Fred10"go2.Middle.Fredsisnull与xsd有类似的问题:DidIjustrunintoaC#error?还是我错过了一些明显的东西?注意:使用名称两次不是问题,如果我创建一个名为George的结构,与Fred相同,并将Middle的内容更改为publicGeorge[]George,问题也不会更好TLDR(对于撇渣器):本文由两部分组成。第1部分:Protobuf快速介绍。这里使用属性。第2部分:问题的实际答案:在不修改继承的情况下为序列化配置库好的,我会试一试。问题似乎是您使用的是CompactFramework,它不具有与完整的.NETFramework相同的序列化/反序列化功能。所以我们需要一些自定义序列化。遵循CompactFramework的理念,我的猜测是您还想要性能良好且占用空间小的东西。所以我选择了Protobuf来完成这项任务(也比XmlSerializer快12倍左右)您可以通过运行来安装它:Install-Packageprotobuf-net让我们从简单的方法开始-通过向模型添加属性。接下来是没有属性的配置,因为您表示不能/不应该修改原始模型。这仅用于说明。使用适当的属性进行装饰,您的模型将如下所示:第1部分:使用属性进行配置。我再说一遍,这部分仅用于说明目的——阅读“没有属性的配置”[ProtoContract]publicstructFred{[ProtoMember(1)]publicstringName;}[ProtoContract]publicstructMiddle{[ProtoMember(1)]publicFred[]Freds;}[ProtoContract]publicstructTop{[ProtoMember(1)]publicMiddleMiddle;[ProtoMember(2)]publicFred[]Freds;}这里唯一要注意的是编号成员的使用,称为键。在JSON或XML序列化的情况下,它基本上与为它们提供属性名称相同,只是这是protobuf的做法。您只需为同一类中的每个成员分配一个唯一的整数值,这就是大部分时间完成的地方。为了方便起见,让我们添加一个简单的构建器,我们可以从中实例化一个Top,就像示例中那样:Name="Fred20"},newFred{Name="Fred21"}}},Freds=new[]{newFred{Name="Fred10"},newFred{Name="Fred11"}}};返回顶部;我们可以像这样序列化它:ToptopIn=newTopTestBuilder().BuildDefaultTestTop();字符串序列化;使用(varstream=newMemoryStream()){Protobuf.Serializer.Serialize(stream,topIn);stream.Position=0;varreader=newStreamReader(stream);序列化=reader.ReadToEnd();}//输出:“nDC4nbnACKFred20nbnACKFred21DC2bnACKFred10DC2bnACKFred11”并将其反序列化为:ToptopOut;使用(varstream=newMemoryStream()){varwriter=newStreamWriter(stream);writer.Write(序列化);writer.Flush();stream.Position=0;topOut=Protobuf.Serializer.Deserialize(流);如您所见,MemoryStreams有一些管道,但除此之外,其他类型的序列化作业应该看起来很熟悉。同样,一切都可以通过配置自定义TypeModel来完成,从而允许序列化与模型完全解耦。第2部分:没有属性的配置默认情况下,Protobuf使用属性来定义TypeModel,然后将其存储在ProtoBuf.Meta.RuntimeTypeModel.Default中。直接调用静态Protobuf.Serializer时使用此属性。我们也可以定义我们自己的。它需要一些摆弄(注意自己:RTFM)才能使它工作但实际证书它几乎一样简单:varmodel=TypeModel.Create();//第一个参数(映射到ProtoContractAttribute)是要包含的类型。//第二个参数决定是否应用默认行为,//基于属性。由于我们不使用这些,因此没有任何效果。model.Add(typeof(Fred),false);model.Add(typeof(Middle),false);model.Add(typeof(Top),false);//可以通过各自的Type索引访问新添加的MetaType。//第一个参数是唯一的成员编号,类似于ProtoMemberAttribute。//第二个参数是成员在类中声明的名称。//当成员是列表时://第三个参数是项目的类型。//第四个参数是列表本身的类型。模型[typeof(Fred)].Add(1,"姓名");模型[typeof(Middle)].Add(1,"Freds",typeof(Fred),typeof(Fred[]));模型[typeof(Top)].Add(1,"Middle");模型[typeof(Top)].Add(2,“弗雷德”,typeof(Fred),typeof(Fred[]));现在我们要做的就是为这两个函数更改一行代码:Serialization:ToptopIn=newTopTestBuilder().BuildDefaultTestTop();字符串序列化;使用(varstream=newMemoryStream()){model.Serialize(stream,top);stream.Position=0;varreader=newStreamReader(stream);序列化=reader.ReadToEnd();反序列化:ToptopOut;使用(varstream=newMemoryStream()){varwriter=newStreamWriter(stream);writer.Write(序列化);writer.Flush();stream.Position=0;topOut=(顶部)_model。反序列化(流,空,类型(顶部));它的工作方式相同可能添加一个类来保持组织-给它两个公共方法序列化和反序列化,以及一个私有方法BuildTypeModel(从构造函数调用并存储在序列化程序的字段中?)你的调用代码最终看起来像这个:varserializer=newCustomProtoBufSerializer();varserialized=serializer.Serialize(someClassInput);SomeClasssomeClassOutput=serializer.Deserialize(序列化);事情很快就清楚了——Protobuf没有像大多数JSON和XML序列化程序那样得到很好的记录和测试。在某些情况下,这与人类无法读取的序列化结果一起是一个缺点。除此之外,它似乎速度快、重量轻并且与许多不同的环境兼容。没有自动类型解析让我很困扰,所以我去寻找并发现了一些非常有趣的东西:ProtobufT4TypeModelGenerator。我还没有尝试过。如果人们感兴趣,我可能会稍后再做,并用更通用的解决方案更新答案。如果您在使用它时遇到任何问题,请告诉我。以上是C#学习教程:.NETCannotdeserializenestedstructures?如果所有分享的内容对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
