当前位置: 首页 > news >正文

网站 宗旨天津网站建设专家

网站 宗旨,天津网站建设专家,抖音营销,网站页面设计制作费目录 一&#xff0c;问题表现 二、没有技术含量的解决方案 三、本人彻底的解决方案 简要说明 贴代码 思路解析 思路 一&#xff0c;问题表现 示例代码如下&#xff1a; [Serializable] public class NodeTest {public NodeTest (){new List<NodeTest> ();}p…

目录

一,问题表现 

二、没有技术含量的解决方案 

三、本人彻底的解决方案

简要说明

贴代码

思路解析

思路


一,问题表现 

示例代码如下:

[Serializable]
public class NodeTest 
{public NodeTest (){new List<NodeTest> ();}public string Name { get; set; }public NodeTest Parent { get; set; }public List<NodeTest> Children { get; set; }}

先看错误地方,以上这个类要是序列化就会遇到,"序列化类型 Test.NodeTest 的对象时检测到循环引用。"错误。

二、没有技术含量的解决方案 

网上一搜,几乎到处都是这两种解决方案:

  1. 使用NewtonSoft.Json,然后使用序列方法,加上设置 ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore
  2. 直接在循环错误属性上加XmlIgnore特性。
                NodeTest nd = new NodeTest ();nd.Name = "root";NodeTest nd1 = new NodeTest ();nd1.Name = "child1";nd1.Parent = nd;NodeTest nd2 = new NodeTest ();nd2.Name = "child2";nd2.Parent = nd;nd.Children.Add ( nd1 );nd.Children.Add ( nd2 );

上面的实例,采用第一种方法序列化是这结果:

 采用第二种是以下结果。

由此可见这两种方法简单,粗暴,没有一点技术含量。这么说是因为,直接忽略了其父子关系。反序列化成对象后Parent属性为空,如果需要逆向查找父对象时,完全行不通。

三、本人彻底的解决方案

  • 简要说明

首先将例中NodeTest对象进行改装,让它继承自 IXmlSerializable 接口并实现,为的就是在序列化和反序列化时,可以自由控制以达到序列化时能包含父节点信息。其次是对他的属性Children进行改造,这很重要,如果继续使用List列表,会出现其他问题,这个后续会提到。

  • 贴代码

现不废话,贴代码,代码看完,看后文解析,应该很容易明白,NodeTest 类:

    [Serializable]public class NodeTest : IXmlSerializable{internal const string ROOT = "NodeTest";internal const string NAME = "Name";internal const string PARENT = "Parent";internal const string ELEMENT_EXISTMARK = "ExistMark";internal const string ELEMENT_EXIST = "Exist";internal const string ELEMENT_NOTEXIST = "NotExist";public NodeTest (){Children = new NodeTestCollection ();}public string Name { get; set; }public NodeTest Parent { get; set; }[XmlArray ()]public NodeTestCollection/*List<NodeTest>*/ Children { get; set; }public System.Xml.Schema.XmlSchema GetSchema (){return null;}public static void ResetSerializationStatus (){_dicAllNodes.Clear ();}private static Dictionary<string, NodeTest> _dicAllNodes= new Dictionary<string, NodeTest> ();public void ReadXml ( System.Xml.XmlReader reader ){XmlSerializer xmlSer = XmlSerializer.FromTypes ( new Type[ ] { typeof ( NodeTest ) } )[ 0 ];if ( reader.IsEmptyElement ) return;while ( reader.NodeType != System.Xml.XmlNodeType.EndElement ){reader.ReadStartElement ( ROOT );reader.ReadStartElement ( NAME );this.Name = reader.ReadString ();reader.ReadEndElement ();reader.MoveToContent ();string sExistMark = ELEMENT_NOTEXIST;if ( reader.MoveToAttribute ( ELEMENT_EXISTMARK ) ){sExistMark = reader.GetAttribute ( ELEMENT_EXISTMARK );}reader.ReadStartElement ( PARENT );switch ( sExistMark ){case ELEMENT_EXIST:reader.ReadStartElement ( NAME );Parent = new NodeTest ();Parent.Name = reader.ReadString ();reader.ReadEndElement ();reader.ReadEndElement ();break;default:break;}XmlSerializer xmlSer2 = XmlSerializer.FromTypes ( new Type[ ] { typeof ( NodeTestCollection ) } )[ 0 ];Children = ( NodeTestCollection )xmlSer2.Deserialize ( reader );if ( Children.Count != 0 ){reader.ReadEndElement ();}_dicAllNodes.Add ( this.Name, this );}for ( int i = 0 ; i < Children.Count ; i++ ){var child = Children[ i ];if ( child.Parent != null ){child.Parent = _dicAllNodes[ child.Parent.Name ];}}}public void WriteXml ( System.Xml.XmlWriter writer ){XmlSerializer xmlSer = XmlSerializer.FromTypes ( new Type[ ] { typeof ( NodeTest ) } )[ 0 ];writer.WriteStartElement ( NAME );writer.WriteString ( this.Name );writer.WriteEndElement ();writer.WriteStartElement ( PARENT );if ( Parent != null ){writer.WriteAttributeString ( ELEMENT_EXISTMARK, ELEMENT_EXIST );writer.WriteStartElement ( NAME );writer.WriteString ( Parent.Name );writer.WriteEndElement ();}else{writer.WriteAttributeString ( ELEMENT_EXISTMARK, ELEMENT_NOTEXIST );}writer.WriteEndElement ();writer.Flush ();XmlSerializer xmlSer2 = XmlSerializer.FromTypes ( new Type[ ] { typeof ( NodeTestCollection ) } )[ 0 ];xmlSer2.Serialize ( writer, this.Children );writer.Flush ();writer.Flush ();}}

List<NodeTest>改成NodeTestCollection,解决序列化时结构错乱问题(本来打算细说的,算了,懒得打字了,看客自己试试就知道了),此改动,还很利于后续的优化扩展,比如名字索引等,实现如下:

    [Serializable][XmlRoot(ElementName = "Children" )]public class NodeTestCollection : IList<NodeTest>, IXmlSerializable{private const string ROOT = "Children";private const string CHILDCOUNT = "ChildCount";#region 继承实现自IList<NodeTest>private IList<NodeTest> m_lstNodes = new List<NodeTest> ();public int IndexOf ( NodeTest item ){int iIdx = -1;for ( int i = 0 ; i < m_lstNodes.Count ; i++ ){if ( m_lstNodes[ i ] == item ){iIdx = i;break;}}return iIdx;}public void Insert ( int index, NodeTest item ){m_lstNodes.Insert ( index, item );}[XmlElement ( "NodeTest", Type = typeof ( NodeTest ) )]public NodeTest this[ int index ]{get{return m_lstNodes[ index ];}set{m_lstNodes[ index ] = value;}}public void Add ( NodeTest item ){m_lstNodes.Add ( item );}public bool Contains ( NodeTest item ){return m_lstNodes.Contains ( item );}public void CopyTo ( NodeTest[ ] array, int arrayIndex ){m_lstNodes.CopyTo ( array, arrayIndex );}public bool Remove ( NodeTest item ){return m_lstNodes.Remove ( item );}IEnumerator<NodeTest> IEnumerable<NodeTest>.GetEnumerator (){return m_lstNodes.GetEnumerator ();}public void RemoveAt ( int index ){m_lstNodes.RemoveAt ( index );}public void Clear (){m_lstNodes.Clear ();}public int Count{get { return m_lstNodes.Count; }}public bool IsReadOnly{get { return false; }}System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator (){return m_lstNodes.GetEnumerator ();}#endregionpublic System.Xml.Schema.XmlSchema GetSchema (){return null;}public void ReadXml ( System.Xml.XmlReader reader ){//if ( reader.IsEmptyElement ) return;int iChildCount = 0;if ( reader.MoveToAttribute ( CHILDCOUNT ) ) iChildCount = int.Parse ( reader.GetAttribute ( CHILDCOUNT ) );reader.ReadStartElement ( ROOT );if (iChildCount > 0){XmlSerializer xmlSer = XmlSerializer.FromTypes ( new Type[ ] { typeof ( NodeTest ) } )[ 0 ];for ( int i = 0 ; i < iChildCount ; i++ ){var readerSub = reader.ReadSubtree();this.Add ( ( NodeTest )xmlSer.Deserialize ( readerSub ) );reader.ReadEndElement ();}}}public void WriteXml ( System.Xml.XmlWriter writer ){int iCnt = this.Count;writer.WriteAttributeString ( CHILDCOUNT, iCnt.ToString () );XmlSerializer xmlSer = XmlSerializer.FromTypes ( new Type[ ] { typeof ( NodeTest ) } )[ 0 ];for ( int i = 0 ; i < iCnt ; i++ ){xmlSer.Serialize ( writer, this[ i ] );}}}
  • 思路解析

说说思路:改造的地方不多,主要是继承方法的实现上,也就是ReadXml WriteXml方法实现上。在实现它们时,采用一点手段,在方法体类对循环引用的对象进行区别处理。

思路

原理很简单,循环引用的地方,在本例中即Parent对象,采用简单存储,存储一个指引信息,这里为图简洁,直接使用Name属性作为指引【后续各位观众具体使用是可以使用唯一标识符进行优化,在此我就不改了】。将所有NodeTest对象信息存为字典,在反序列化时使用指引进行挂接,因为这是class,是引用对象,简单一改,全部挂接完成,挂接处就是For循环处。

此外还有两处XmlAttribute——ExistMark和ChildCount,分别用来辅助Parent存在时检测以及子节点存在检测。

采用这个方法,序列化出来如下图:

 

反序列化也成功进行挂接,不信,你试试。

原理就这么简单。

 不懂就留言吧。

http://www.yayakq.cn/news/427027/

相关文章:

  • 网站空间在哪买好网站工信部备案流程
  • 哪个网站上做ppt比较好看的html5网站建设
  • 苏州网站建设营销网络系统安全原则
  • 如何给网站流量来源做标记通过在网址后边加问号?找图网
  • 免费建站 永久怎样打开网站
  • 江苏建设厅网站谷歌推广
  • 用html5的视频网站wordpress字段插件
  • 手机网站制作平台网络广告设计课程
  • 网站搭建培训视频弹幕网站怎么做的
  • 网站建设考察报告网站建设采购公告
  • 南京网站建设索q.479185700建设网站证
  • 成都网站推广 优帮云浙江杭州软件公司排名
  • 安阳建设网站网站建设 域名 服务器
  • 正规的合肥网站建设宣传产品的方式
  • 郑州做网站kuihuakeji电销防封号系统
  • 网站建设的规划书国土资源部门网站建设制度
  • 公司建设网站费用吗wordpress情侣
  • 网站建设有哪些基本流程wordpress home
  • 若要使用链接目标在新窗口打开北京网络优化
  • 没有网站可以做域名解析吗东莞住房和城乡建设网
  • 医疗网站开发ppt抖音电商官网
  • 一个专做窗帘的网站手机网页设计尺寸规范
  • 福建建设信息网站网站的建设与维护步骤
  • 河南省教育类网站前置审批哪个网站做外贸好
  • 做电商网站需要会些什么wordpress 整站 数据
  • 昆明做网站找哪个公司好中国十大广告公司排行榜
  • 怎么样自己开网站网站建设的系统简介
  • 哪个网站原创文章有没有做网站的公司
  • wordpress图片路径网站seo的关键词排名怎么做的
  • 百度关键词优化企业seo网站关键词优化哪家好