using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Linq; using System.Net; namespace Misc { public class SaveToXmlHepler { #region IBaseSaveToXml,ISaveToXml 列表 public static void Regist(Type type, IBaseSaveToXml ie) { mBase.Regist(type, ie); } public static void Regist(Type type) { mBase.Regist(type); } private class BASE { public Dictionary<Type, IBaseSaveToXml> base_elements = new Dictionary<Type, IBaseSaveToXml>(); public List<Type> elements = new List<Type>(); public BASE() { //base object base_elements.Add(typeof(bool), new BaseSaveToXml_Bool()); base_elements.Add(typeof(int), new BaseSaveToXml_Int()); base_elements.Add(typeof(uint), new BaseSaveToXml_UInt32()); base_elements.Add(typeof(double), new BaseSaveToXml_Double()); base_elements.Add(typeof(float), new BaseSaveToXml_Float()); base_elements.Add(typeof(string), new BaseSaveToXml_String()); base_elements.Add(typeof(TimeSpan), new BaseSaveToXml_TimeSpan()); base_elements.Add(typeof(DateTime), new BaseSaveToXml_DateTime()); base_elements.Add(typeof(IPEndPoint), new BaseSaveToXml_IPEndPoint()); } public void Regist(Type type, IBaseSaveToXml ie) { if (!base_elements.Keys.Contains(type)) { base_elements.Add(type, ie); } } public void Regist(Type type) { int cnt = (from e in elements where e.Equals(type) select e).Count(); if (cnt == 0) elements.Add(type); } /// <summary> /// Save, 支持数组 /// </summary> /// <param name="name"></param> /// <param name="value"></param> /// <returns></returns> public XObject GetXObject(string name, object value) { if (value == null) return null; Type type = value.GetType(); //if( type. System.Collections.IEnumerable if ((typeof(System.Collections.IList).IsAssignableFrom(type))|| (type.BaseType.Equals(typeof(Array)))) { XElement root = new XElement(name); System.Collections.IList list = (System.Collections.IList)value; foreach (object obj in list) { XObject xobj = GetXObject(obj.GetType().Name, obj); if (xobj != null) { root.Add(xobj); } } return root; } else if (base_elements.Keys.Contains(type)) { IBaseSaveToXml e = base_elements[type]; return e.GetXObject(name, value); } else if (type.BaseType.Equals(typeof(Enum))) { return new XAttribute(name, value.ToString()); } //else if (typeof(ISaveToXml).IsAssignableFrom(type)) else { List<string> propertyNames = new List<string>(); if (typeof(ISaveToXml).IsAssignableFrom(type)) { propertyNames.AddRange((value as ISaveToXml).GetSavePropertyNames()); } if (propertyNames.Count() == 0) { propertyNames.AddRange(type.GetProperties().Select(new Func<System.Reflection.PropertyInfo, string>( delegate(System.Reflection.PropertyInfo p) { return p.Name; }))); propertyNames.AddRange(type.GetFields().Select(new Func<System.Reflection.FieldInfo, string>( delegate(System.Reflection.FieldInfo p) { return p.Name; }))); } XElement root = new XElement(name); foreach (string propertyName in propertyNames) { System.Reflection.PropertyInfo pi = type.GetProperty(propertyName); if (pi != null) { object v = pi.GetValue(value, null); XObject xobj = GetXObject(propertyName, v); if (xobj != null) root.Add(xobj); continue; } System.Reflection.FieldInfo fi = type.GetField(propertyName); if (fi != null) { object v = fi.GetValue(value); XObject xobj = GetXObject(propertyName, v); if (xobj != null) root.Add(xobj); continue; } } return root; } } //Load public bool TryParse(Type type, XObject xobj, ref object value) { if ((typeof(System.Collections.IList).IsAssignableFrom(type)) || ((type.BaseType!=null) && (type.BaseType.Equals(typeof(Array))))) { if (value == null)//数组不能为空 return false; System.Collections.IList list = (System.Collections.IList)value; list.Clear(); //数组怎样移除? //当为数组时, 如 int[] a=new int[3]; //执行 list.Clear() , a.length 还是=3, 但a[0]=0, 当类型不是常量 a[0]=null XElement e = xobj as XElement;//肯定是 XElement int idx = 0; foreach (XElement _e in e.Elements()) { //可以从 _e.Name 解析出类型 { var kvs = from __e in base_elements where __e.Key.Name.CompareTo(_e.Name.LocalName) == 0 select __e; if (kvs.Count() > 0) { var kv = kvs.First(); object v = null; kv.Value.TryParse(_e, ref v); if (list.IsFixedSize)//固定长度 { if (idx < list.Count) { list[idx] = v; idx++; } } else { list.Add(v); } continue; } } { var kvs = from __e in elements where __e.Name.CompareTo(_e.Name.LocalName) == 0 select __e; if (kvs.Count() > 0) { var kv = kvs.First(); object v = Activator.CreateInstance(kv); TryParse(kv, _e, ref v); if (list.IsFixedSize)//固定长度 { if (idx < list.Count) { list[idx] = v; idx++; } } else { list.Add(v); } continue; } } } return true; } else if(base_elements.Keys.Contains(type)) { IBaseSaveToXml basesavetoxml = base_elements[type]; return basesavetoxml.TryParse(xobj, ref value); } else if ( (type.BaseType!=null) && (type.BaseType.Equals(typeof(Enum)))) { string xmlvalue=""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } value = Enum.Parse(type, xmlvalue); return true; } else// if (typeof(ISaveToXml).IsAssignableFrom(type)) { XElement e = xobj as XElement;//肯定是 XElement foreach (XAttribute attr in e.Attributes()) { System.Reflection.PropertyInfo pi = type.GetProperty(attr.Name.LocalName); if (pi != null) { Type propertyType = pi.PropertyType; object obj = pi.GetValue(value, null); TryParse(propertyType, attr, ref obj); try { pi.SetValue(value, obj, null); } catch { //失败,不处理 } continue; } System.Reflection.FieldInfo fi = type.GetField(attr.Name.LocalName); if (fi != null) { Type propertyType = fi.FieldType; object obj = fi.GetValue(value); TryParse(propertyType, attr, ref obj); fi.SetValue(value, obj); continue; } } foreach (XElement element in e.Elements()) { System.Reflection.PropertyInfo pi = type.GetProperty(element.Name.LocalName); if (pi != null) { Type propertyType = pi.PropertyType; object obj = pi.GetValue(value, null); TryParse(propertyType, element, ref obj); } System.Reflection.FieldInfo fi = type.GetField(element.Name.LocalName); if (fi != null) { Type propertyType = fi.FieldType; object obj = fi.GetValue(value); TryParse(propertyType, element, ref obj); fi.SetValue(value, obj); continue; } } return true; } } } private static BASE mBase = new BASE(); #endregion //数据加载到指定 object public static bool Load(string path, Object obj) { Type type = obj.GetType(); //if (!typeof(ISaveToXml).IsAssignableFrom(type)) //{ // return false; //} SaveToXmlHepler.Regist(obj.GetType()); if (!System.IO.File.Exists(path)) { return Save(path, obj); } XElement root = null; try { root = XElement.Load(path); } catch (Exception e) { } if (root == null) { return Save(path, obj); } //从 mBase 获取 ISaveToXml 列表 信息 mBase.TryParse(type, root, ref obj); return true; } public static bool Save(string path, Object obj) { if (obj == null)//没数据,不用保存 return false; Type type = obj.GetType(); //SaveToXmlHepler.Regist(obj.GetType());//没用,都要求在类中 static classname(){ SaveToXmlHepler.Regist(typeof(classname)); } XObject xobj = mBase.GetXObject(obj.GetType().Name, obj); string dirpath=System.IO.Path.GetDirectoryName(path); if (!string.IsNullOrEmpty(dirpath)) { if (!System.IO.Directory.Exists(dirpath)) { System.IO.Directory.CreateDirectory(dirpath); } } if (xobj != null) (xobj as XElement).Save(path); return true; } } public interface ISaveToXml { /// <summary> /// 获取需要保存的属性名字列表 /// </summary> /// <returns></returns> string[] GetSavePropertyNames(); } public interface IBaseSaveToXml { XObject GetXObject(string name, object value); bool TryParse(XObject xobj, ref object value); } #region base object class BaseSaveToXml_UInt32 : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if (name.CompareTo(typeof(int).Name) == 0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public virtual bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } uint result = 0; if (uint.TryParse(xmlvalue, out result)) { value = result; return true; } return false; } } class BaseSaveToXml_Int : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if(name.CompareTo(typeof(int).Name)==0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public virtual bool TryParse(XObject xobj, ref object value) { string xmlvalue=""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if(attr!=null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } int result = 0; if (int.TryParse(xmlvalue, out result)) { value = result; return true; } return false; } } class BaseSaveToXml_String : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if(name.CompareTo(typeof(string).Name)==0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } value = xmlvalue; return true; } } class BaseSaveToXml_Double : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if (name.CompareTo(typeof(double).Name) == 0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } double result = 0; if (double.TryParse(xmlvalue, out result)) { value = result; return true; } return false; } } class BaseSaveToXml_Float : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if (name.CompareTo(typeof(double).Name) == 0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } float result = 0; if (float.TryParse(xmlvalue, out result)) { value = result; return true; } return false; } } class BaseSaveToXml_Bool : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if (name.CompareTo(typeof(bool).Name) == 0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } bool result = false; if (bool.TryParse(xmlvalue, out result)) { value = result; return true; } return false; } } class BaseSaveToXml_TimeSpan : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if (name.CompareTo(typeof(TimeSpan).Name) == 0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } TimeSpan result = new TimeSpan(1); if (TimeSpan.TryParse(xmlvalue, out result)) { value = result; return true; } return false; } } class BaseSaveToXml_DateTime : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if (name.CompareTo(typeof(DateTime).Name) == 0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } DateTime result = DateTime.MinValue; if (DateTime.TryParse(xmlvalue, out result)) { value = result; return true; } return false; } } class BaseSaveToXml_IPEndPoint : IBaseSaveToXml { public XObject GetXObject(string name, object value) { if (name.CompareTo(typeof(IPEndPoint).Name) == 0) { return new XElement(name, GetXObject("value", value)); } else { return new XAttribute(name, value.ToString()); } } public bool TryParse(XObject xobj, ref object value) { string xmlvalue = ""; if (xobj is XElement) { XAttribute attr = (xobj as XElement).Attribute("value"); if (attr != null) xmlvalue = attr.Value; } else if (xobj is XAttribute) { xmlvalue = (xobj as XAttribute).Value; } IPEndPoint result = Misc.StringConverter.ToIPEndPoint(xmlvalue); value = result; return true; } } #endregion #region 测试 public enum Sex { Male, FeMale } public class ISaveToXml_Test// : ISaveToXml { public int A { get; set; } private List<int> _B = new List<int>(); public List<int> B { get { return _B; } } private int[] _C = new int[3] { 0, 0, 2 }; public int[] C { get { return _C; } } public Sex Sex; #region ISaveToXml 成员 //public string[] GetSavePropertyNames() //{ // return new string[]{ // "A","B","C","Sex"}; //} #endregion public static void Main() { ISaveToXml_Test test = new ISaveToXml_Test() { A = 1, Sex = Sex.FeMale }; test.B.Add(3); test.B.Add(4); test.C[1] = 10; SaveToXmlHepler.Save(@"D:\123.xml", test); test.C[1] = 3; SaveToXmlHepler.Load(@"D:\123.xml", test); } } #endregion }