对象与Xml的相互转化

    .Net中的XmlSerializer非常好用,但是有时候也不能完全满足要求。比如XmlSerializer完全按照对象内容展开,而不管引用关系,造成在反序列化后对象结构和原始的会不一致,如果循环引用还会出现死循环;需要显式制定对象中所有的自定义类型,不够方便;不支持范型,不能用接口作为变量类型等等。
    自己写了一段程序,某些时候用起来比较方便,也为了熟悉一下Xml操作。很久以前写的了,现在看一下还是有一些不足之处,以后有需要再修改吧。
  1. using   System; 
  2. using   System.Collections.Generic; 
  3. using   System.Text; 
  4. using   System.Xml; 
  5. using   System.IO; 
  6. using   System.Reflection; 
  7. using   System.Runtime.Serialization; 
  8. using   System.Collections; 
  9. namespace   System 
  10.         public   static   class   XMLConvert 
  11.         { 
  12.                 private   const   string   tag_reference   =   "ref "
  13.                 private   const   string   tag_type   =   "type "
  14.                 private   const   string   tag_param   =   "params "
  15.                 private   const   char   char_left   =   '( '
  16.                 private   const   char   char_right   =   ') '
  17.                 private   static   Assembly[]   assemblies   =   AppDomain.CurrentDomain.GetAssemblies(); 
  18.                 
  19.                 public   static   string   ToXML(object   o) 
  20.                 { 
  21.                         return   ToXML( "class ",   o); 
  22.                 } 
  23.                 public   static   string   ToXML(string   name,   object   o) 
  24.                 { 
  25.                         StringBuilder   stringBuilder   =   new   StringBuilder(); 
  26.                         XmlTextWriter   xmlWriter   =   new   XmlTextWriter(new   StringWriter(stringBuilder)); 
  27.                         xmlWriter.Formatting   =   Formatting.Indented; 
  28.                         xmlWriter.WriteStartDocument(); 
  29.                         ToXML(name,   o,   xmlWriter,   new   Hashtable()); 
  30.                         xmlWriter.WriteEndDocument(); 
  31.                         return   stringBuilder.ToString(); 
  32.                 } 
  33.                 public   static   object   ToObject(string   strXML) 
  34.                 { 
  35.                         XmlDocument   xml   =   new   XmlDocument(); 
  36.                         xml.LoadXml(strXML); 
  37.                         return   ToObject(xml); 
  38.                 } 
  39.                 public   static   object   ToObject(XmlDocument   xml) 
  40.                 { 
  41.                         Hashtable   refMap   =   new   Hashtable(xml.ChildNodes.Count   *   4); 
  42.                         object   value   =   ToObject(xml.LastChild,   refMap); 
  43.                         return   value; 
  44.                 } 
  45.                 private   static   void   ToXML(string   name,   object   value,   XmlWriter   xmlWriter,   Hashtable   refMap) 
  46.                 { 
  47.                         xmlWriter.WriteStartElement(name); 
  48.                         if   (value   !=   null
  49.                         { 
  50.                                 if   (refMap.ContainsKey(new   Ref(value))) 
  51.                                 { 
  52.                                         xmlWriter.WriteAttributeString(tag_reference,   refMap[new   Ref(value)].ToString()); 
  53.                                 } 
  54.                                 else 
  55.                                 { 
  56.                                         Type   type   =   value.GetType(); 
  57.                                         TypeToXML(type,   xmlWriter); 
  58.                                         if   (!type.IsValueType) 
  59.                                         { 
  60.                                                 xmlWriter.WriteAttributeString(tag_reference,   refMap.Count.ToString()); 
  61.                                                 refMap.Add(new   Ref(value),   refMap.Count); 
  62.                                         } 
  63.                                         if   (type.IsPrimitive   ||   type.Equals(typeof(string))) 
  64.                                         { 
  65.                                                 xmlWriter.WriteString(Convert.ToString(value)); 
  66.                                         } 
  67.                                         else   if   (type.IsArray) 
  68.                                         { 
  69.                                                 foreach   (object   subvalue   in   (value   as   Array)) 
  70.                                                 { 
  71.                                                         ToXML( "element ",   subvalue,   xmlWriter,   refMap); 
  72.                                                 } 
  73.                                         } 
  74.                                         else 
  75.                                         { 
  76.                                                 ToXML(type,   value,   xmlWriter,   refMap); 
  77.                                         } 
  78.                                 } 
  79.                         } 
  80.                         xmlWriter.WriteEndElement(); 
  81.                 } 
  82.  private   static   void   ToXML(Type   type,   object   value,   XmlWriter   xmlWriter,   Hashtable   refMap) 
  83.                 { 
  84.                         if   (type   ==   null   ||   type.Equals(typeof(object)))   return
  85.                         FieldInfo[]   fields   =   type.GetFields(BindingFlags.GetField   |   BindingFlags.Instance   |   BindingFlags.Public   |   BindingFlags.NonPublic); 
  86.                         foreach   (FieldInfo   field   in   fields) 
  87.                         { 
  88.                                 ToXML(field.Name,   field.GetValue(value),   xmlWriter,   refMap); 
  89.                         } 
  90.                         ToXML(type.BaseType,   value,   xmlWriter,   refMap); 
  91.                 } 
  92.                 private   static   void   TypeToXML(Type   type,   XmlWriter   xmlWriter) 
  93.                 { 
  94.                         if   (type.IsGenericType) 
  95.                         { 
  96.                                 Type   genericType   =   type.GetGenericTypeDefinition(); 
  97.                                 xmlWriter.WriteAttributeString(tag_type,   genericType.FullName); 
  98.                                 Type[]   genericArguments   =   type.GetGenericArguments(); 
  99.                                 xmlWriter.WriteAttributeString(tag_param,   ToParamsName(genericArguments)); 
  100.                         } 
  101.                         else 
  102.                         { 
  103.                                 xmlWriter.WriteAttributeString(tag_type,   type.FullName); 
  104.                         } 
  105.                 } 
  106.                 private   static   string   ToParamsName(Type[]   genericArguments) 
  107.                 { 
  108.                         string[]   names   =   new   string[genericArguments.Length]; 
  109.                         for   (int   i   =   0;   i   <   genericArguments.Length;   i++) 
  110.                         { 
  111.                                 if   (genericArguments[i].IsGenericType) 
  112.                                         names[i]   =   genericArguments[i].GetGenericTypeDefinition().FullName   +   char_left   +   ToParamsName(genericArguments[i].GetGenericArguments())   +   char_right; 
  113.                                 else 
  114.                                         names[i]   =   genericArguments[i].FullName; 
  115.                         } 
  116.                         return   String.Join( ",   ",   names); 
  117.                 } 
  118.                 private   static   object   ToObject(XmlNode   node,   Hashtable   refMap) 
  119.                 { 
  120.                         if   (node   ==   null   ||   node.Attributes.Count   ==   0)   return   null
  121.                         if   (node.Attributes[tag_reference]   !=   null   &&   refMap[Int32.Parse(node.Attributes[tag_reference].Value)]   !=   null)   return   refMap[Int32.Parse(node.Attributes[tag_reference].Value)]; 
  122.                         Type   type   =   GetType(node.Attributes[tag_type].Value); 
  123.                         if   (type.IsGenericTypeDefinition) 
  124.                         { 
  125.                                 string   paramName   =   node.Attributes[tag_param].Value; 
  126.                                 type   =   GetGenericType(type,   paramName); 
  127.                         } 
  128.                         object   value   =   null
  129.                         if   (type.Equals(typeof(IntPtr))) 
  130.                         { 
  131.                                 value   =   (IntPtr)Convert.ToInt32(node.InnerText); 
  132.                         } 
  133.                         else   if   (type.IsPrimitive   ||   type.Equals(typeof(string))) 
  134.                         { 
  135.                                 value   =   Convert.ChangeType(node.InnerText,   type); 
  136.                         } 
  137.                         else   if   (type.IsArray) 
  138.                         { 
  139.                                 value   =   Array.CreateInstance(type.GetElementType(),   node.ChildNodes.Count); 
  140.                         } 
  141.                         else 
  142.                         { 
  143.                                 value   =   FormatterServices.GetUninitializedObject(type); 
  144.                         } 
  145.                         if   (node.Attributes[tag_reference]   !=   null)   refMap[Int32.Parse(node.Attributes[tag_reference].Value)]   =   value; 
  146.                         if   (type.Equals(typeof(IntPtr)))   {   } 
  147.                         else   if   (type.IsPrimitive   ||   type.Equals(typeof(string)))   {   } 
  148.                         else   if   (type.IsArray) 
  149.                         { 
  150.                                 for   (int   i   =   0;   i   <   node.ChildNodes.Count;   i++) 
  151.                                 { 
  152.                                         (value   as   Array).SetValue(ToObject(node.ChildNodes[i],   refMap),   i); 
  153.                                 } 
  154.                         } 
  155.                         else 
  156.                         { 
  157.                                 foreach   (XmlNode   xmlnode   in   node.ChildNodes) 
  158.                                 { 
  159.                                         FieldInfo   field   =   GetField(type,   xmlnode.Name); 
  160.                                         field.SetValue(value,   ToObject(xmlnode,   refMap)); 
  161.                                 } 
  162.                         } 
  163.                         return   value; 
  164.                 } 
  165. private   static   Type   GetType(string   name) 
  166.                 { 
  167.                         int   index1   =   name.IndexOf(char_left); 
  168.                         int   index2   =   name.LastIndexOf(char_right); 
  169.                         if   (index1   <   0) 
  170.                         { 
  171.                                 Type   type   =   Type.GetType(name); 
  172.                                 if   (type   ==   null
  173.                                 { 
  174.                                         foreach   (Assembly   assembly   in   assemblies) 
  175.                                         { 
  176.                                                 type   =   assembly.GetType(name); 
  177.                                                 if   (type   !=   null)   break
  178.                                         } 
  179.                                 } 
  180.                                 return   type; 
  181.                         } 
  182.                         else 
  183.                         { 
  184.                                 return   GetGenericType(GetType(name.Substring(0,   index1)),   name.Substring(index1   +   1,   index2   -   index1   -   1)); 
  185.                         } 
  186.                 } 
  187.                 private   static   FieldInfo   GetField(Type   type,   string   name) 
  188.                 { 
  189.                         FieldInfo   field   =   null
  190.                         while   (field   ==   null   &&   type   !=   null
  191.                         { 
  192.                                 field   =   type.GetField(name,   BindingFlags.Instance   |   BindingFlags.Public   |   BindingFlags.NonPublic); 
  193.                                 type   =   type.BaseType; 
  194.                         } 
  195.                         return   field; 
  196.                 } 
  197.                 private   static   Type   GetGenericType(Type   type,   string   param) 
  198.                 { 
  199.                         string[]   paramNames   =   Split(param,   ', ',   char_left,   char_right); 
  200.                         Type[]   paramTypes   =   new   Type[paramNames.Length]; 
  201.                         for   (int   i   =   0;   i   <   paramNames.Length;   i++) 
  202.                         { 
  203.                                 paramTypes[i]   =   GetType(paramNames[i]); 
  204.                         } 
  205.                         return   type.MakeGenericType(paramTypes); 
  206.                 } 
  207.                 private   static   string[]   Split(string   str,   char   separator,   char   left,   char   right) 
  208.                 { 
  209.                         List <string>   results   =   new   List <string> (str.Length   /   10); 
  210.                         int   start   =   0; 
  211.                         for   (int   i   =   0,   stack   =   0;   i   <   str.Length;   i++) 
  212.                         { 
  213.                                 if   (str[i]   ==   separator   &&   stack   ==   0) 
  214.                                 { 
  215.                                         results.Add(str.Substring(start,   i   -   start)); 
  216.                                         start   =   i   +   1; 
  217.                                 } 
  218.                                 if   (str[i]   ==   left)   stack++; 
  219.                                 if   (str[i]   ==   right)   stack--; 
  220.                         } 
  221.                         if   (start   <   str.Length)   results.Add(str.Substring(start)); 
  222.                         return   results.ToArray(); 
  223.                 } 
  224.                 class   Ref 
  225.                 { 
  226.                         private   object   value   =   null
  227.                         public   Ref(object   o) 
  228.                         { 
  229.                                 value   =   o; 
  230.                         } 
  231.                         public   override   bool   Equals(object   obj) 
  232.                         { 
  233.                                 if   (obj   is   Ref   &&   ReferenceEquals(value,   (obj   as   Ref).value))   return   true
  234.                                 else   return   false
  235.                         } 
  236.                         public   override   int   GetHashCode() 
  237.                         { 
  238.                                 if   (value   !=   null)   return   value.GetHashCode(); 
  239.                                 else   return   0; 
  240.                         } 
  241.                 } 
  242.         } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值