| using System; | 
| using System.Collections; | 
| using System.Collections.Generic; | 
| using System.Reflection; | 
| using System.Text; | 
|   | 
| namespace Top.Api.Util | 
| { | 
|     public class XmlWriter | 
|     { | 
|         private StringBuilder buf = new StringBuilder(); | 
|         private Stack<object> calls = new Stack<object>(); | 
|         private string rootTagName; | 
|         private Type stopType; | 
|         private IDictionary<string, object> stopProps; | 
|   | 
|         public XmlWriter(string rootTagName, Type stopType) | 
|         { | 
|             this.rootTagName = rootTagName; | 
|             this.stopType = stopType; | 
|             if (stopType != null) | 
|             { | 
|                 this.stopProps = GetStopProps(stopType); | 
|             } | 
|         } | 
|   | 
|         public XmlWriter() | 
|             : this(null, null) | 
|         { | 
|         } | 
|   | 
|         public string Write(object obj) | 
|         { | 
|             buf.Length = 0; | 
|             string tagName = rootTagName; | 
|             if (tagName == null) | 
|             { | 
|                 tagName = StringUtil.ToCamelStyle(obj.GetType().Name); | 
|             } | 
|             AddPair(tagName, obj); | 
|             return buf.ToString(); | 
|         } | 
|   | 
|         private void Value(object obj) | 
|         { | 
|             if (obj == null || Cyclic(obj)) | 
|             { | 
|                 AddObject(null); | 
|             } | 
|             else | 
|             { | 
|                 calls.Push(obj); | 
|                 Type objType = obj.GetType(); | 
|                 if (typeof(IDictionary).IsAssignableFrom(objType)) | 
|                 { | 
|                     AddDictionary(obj as IDictionary); | 
|                 } | 
|                 else if (typeof(ICollection).IsAssignableFrom(objType)) | 
|                 { | 
|                     AddCollection(obj as ICollection); | 
|                 } | 
|                 else if (objType.IsArray) | 
|                 { | 
|                     AddArray(obj); | 
|                 } | 
|                 else if (typeof(DateTime) == objType) | 
|                 { | 
|                     AddDateTime((DateTime)obj); | 
|                 } | 
|                 else if (typeof(bool) == objType) | 
|                 { | 
|                     AddBool((bool)obj); | 
|                 } | 
|                 else if (typeof(string) == objType || typeof(Type) == objType) | 
|                 { | 
|                     AddString(obj); | 
|                 } | 
|                 else if (objType.IsPrimitive) | 
|                 { | 
|                     AddString(obj); | 
|                 } | 
|                 else | 
|                 { | 
|                     AddBean(obj); | 
|                 } | 
|                 calls.Pop(); | 
|             } | 
|         } | 
|   | 
|         private bool Cyclic(object obj) | 
|         { | 
|             Stack<object>.Enumerator em = calls.GetEnumerator(); | 
|             while (em.MoveNext()) | 
|             { | 
|                 object called = em.Current; | 
|                 if (obj == called) return true; | 
|             } | 
|             return false; | 
|         } | 
|   | 
|         private void AddBean(object obj) | 
|         { | 
|             bool isChildren = stopType != null && stopType.IsAssignableFrom(obj.GetType()); | 
|             PropertyInfo[] props = obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty); | 
|             foreach (PropertyInfo prop in props) | 
|             { | 
|                 string name = prop.Name; | 
|                 if (isChildren && stopProps.ContainsKey(name)) | 
|                 { | 
|                     continue; | 
|                 } | 
|                 object value = prop.GetValue(obj, new object[] { }); | 
|                 if (value != null) | 
|                 { | 
|                     string newName = StringUtil.ToCamelStyle(name); | 
|                     AddPair(newName, value); | 
|                 } | 
|             } | 
|         } | 
|   | 
|         private void AddDictionary(IDictionary obj) | 
|         { | 
|             foreach (DictionaryEntry entry in obj) | 
|             { | 
|                 string strKey = entry.Key.ToString(); | 
|                 AddPair(strKey, entry.Value); | 
|             } | 
|         } | 
|   | 
|         private void AddCollection(ICollection obj) | 
|         { | 
|             string tagName = null; | 
|             foreach (object item in obj) | 
|             { | 
|                 if (tagName == null) | 
|                 { | 
|                     object[] apiListTypes = item.GetType().GetCustomAttributes(typeof(ApiListTypeAttribute), false); | 
|                     if (apiListTypes != null && apiListTypes.Length > 0) | 
|                     { | 
|                         tagName = ((ApiListTypeAttribute) apiListTypes[0]).Value; | 
|                     } | 
|                     else | 
|                     { | 
|                         tagName = StringUtil.ToCamelStyle(obj.GetType().Name); | 
|                     } | 
|                 } | 
|                 AddPair(tagName, item); | 
|             } | 
|         } | 
|   | 
|         private void AddArray(object obj) | 
|         { | 
|             string tagName = null; | 
|             Array.ForEach(obj as object[], item => | 
|             { | 
|                 if (tagName == null) | 
|                 { | 
|                     tagName = StringUtil.ToCamelStyle(obj.GetType().Name); | 
|                 } | 
|                 AddPair(tagName, item); | 
|             }); | 
|         } | 
|   | 
|         private void AddBool(bool value) | 
|         { | 
|             AddObject(value ? "true" : "false"); | 
|         } | 
|   | 
|         private void AddDateTime(DateTime value) | 
|         { | 
|             AddObject(StringUtil.FormatDateTime(value)); | 
|         } | 
|   | 
|         private void AddString(object obj) | 
|         { | 
|             AddObject(StringUtil.EscapeXml(obj.ToString())); | 
|         } | 
|   | 
|         private void AddObject(object obj) | 
|         { | 
|             buf.Append(obj); | 
|         } | 
|   | 
|         private void AddPair(string name, object value) | 
|         { | 
|             StartTag(name); | 
|             Value(value); | 
|             EndTag(name); | 
|         } | 
|   | 
|         private void StartTag(string tagName) | 
|         { | 
|             buf.Append("<"); | 
|             buf.Append(tagName); | 
|             buf.Append(">"); | 
|         } | 
|   | 
|         private void EndTag(string tagName) | 
|         { | 
|             buf.Append("</"); | 
|             buf.Append(tagName); | 
|             buf.Append(">"); | 
|         } | 
|   | 
|         private IDictionary<string, object> GetStopProps(Type type) | 
|         { | 
|             IDictionary<string, object> stopProps = new Dictionary<string, object>(); | 
|             PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty); | 
|             foreach (PropertyInfo prop in props) | 
|             { | 
|                 stopProps.Add(prop.Name, null); | 
|             } | 
|             return stopProps; | 
|         } | 
|     } | 
| } |