C# XML与实体互转,实体类反序列化属性对应转换成 XmlAttribute

一、前言

可扩展标记语言 (XML) 是具有结构性的标记语言,可以用来标记数据、定义数据类型,是一种允许用户对自己的标记语言进行定义的源语言。XML是用来存储数据的,重在数据本身。本文中的代码是几个月前整理的,最近几个月的时间很少写随笔,除了工作以外,主要还是忙于整理自己的框架。这篇随笔主要是针对于XML的特性Attribute与实体之间的匹配与转换,其中的内容包括反射、XML以及LinqToXml,代码的内容也是想到什么就写什么,纯属练习下手感,仅供参考。下一篇随笔将以另外的形式来转换Xml为对象实体,当然,也是以反射为主,和本随笔中的思路差不多,主要是XML的格式和解决方案不同而已。对于如何将对象转换成Xml的话,主要还是看情况,仅仅转换简单的对象的话,直接反射就可以生成。对于复杂的对象的话,可以采用dynamic,树结构和递归算法的方案来定制XML。

XmlAttributeUtility的转换操作相对来说比较简单,采用反射+LinqToXml转换操作就很简单了,主要实现方法为public static XElement Convert<T>(T entity) where T : new(),其他方法都是以该方法作为基础来进行操作。为什么用LinqToXml?主要原因是LinqToXml比Xml更方便,很多细节方面不需要考虑太多。代码如下:

实体类:

  public class Document<T>
    {
        public Document()
        {
            this.OrderMethod = new Util.OrderMethod();
            this.SortMethod = new Util.SortMethod();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="taskGuid"></param>
        /// <param name="dataGuid"></param>
        /// <param name="dataType"></param>
        /// <param name="pageSize"></param>
        /// <param name="pageIndex"></param>
        /// <param name="total"></param>
        /// <param name="requestTime"></param>
        /// <param name="returnTime"></param>
        /// <param name="sortMethod"></param>
        /// <param name="orderMethod"></param>
        public Document(string taskGuid, string dataGuid, string dataType, int pageSize, int pageIndex, int total, string requestTime, string returnTime, string sortMethod, string orderMethod)
        {
            this.TaskGuid = taskGuid;
            this.DataGuid = dataGuid;
            this.DataType = dataType;
            this.PageSize = pageSize;
            this.PageIndex = pageIndex;
            this.Total = total;
            this.RequestTime = requestTime;
            this.ReturnTime = returnTime;
            this.OrderMethod = new Util.OrderMethod() { Value = orderMethod };
            this.SortMethod = new Util.SortMethod() { Value = sortMethod };
        }
        /// <summary>
        /// 组件标识
        /// </summary>
        public string TaskGuid { get; set; }
        /// <summary>
        /// 车辆轨迹回放
        /// </summary>
        public string DataGuid { get; set; }
        /// <summary>
        /// 数据类型
        /// </summary>
        public string DataType { get; set; }
        /// <summary>
        /// 每页记录数
        /// </summary>
        public int PageSize { get; set; }
        /// <summary>
        /// 检索的页号
        /// </summary>
        public int PageIndex { get; set; }
        /// <summary>
        /// 数据量
        /// </summary>
        public int Total { get; set; }
        /// <summary>
        /// 查询请求时间
        /// </summary>
        public string RequestTime { get; set; }
        /// <summary>
        /// 查询结果生成时间
        /// </summary>
        public string ReturnTime { get; set; }
        /// <summary>
        /// 排序字段名
        /// </summary>
        public SortMethod SortMethod { get; set; }
        /// <summary>
        /// 排序方式
        /// </summary>
        public OrderMethod OrderMethod { get; set; }
        /// <summary>
        /// 
        /// </summary>
        public IEnumerable<T> Data { get; set; }
    }



    public class SortMethod
    {
        /// <summary>
        /// TEXT
        /// </summary>
        public string Type { get { return "TEXT"; } }
        /// <summary>
        /// 排序字段名
        /// </summary>
        public string Value { get; set; }
    }

    public class OrderMethod
    {
        /// <summary>
        /// TEXT
        /// </summary>
        public string Type { get { return "TEXT"; } }
        /// <summary>
        /// 排序方式[asc|desc]
        /// </summary>
        public string Value { get; set; }
    }

转换工具类:

namespace XmlConvert.Framework
{
    /// <summary>
    /// Entity to XML Convert
    /// </summary>
    public class XmlAttributeUtility
    {
        public static bool Append<T>(string inputUri, string parentXPath,
            List<T> entities) where T : new()
        {
            return RepalceOrAppend<T>(inputUri, parentXPath, entities, true);
        }

        public static bool Replace<T>(string inputUri, string parentXPath,
            List<T> entities) where T : new()
        {
            return RepalceOrAppend<T>(inputUri, parentXPath, entities, false);
        }

        public static bool RepalceOrAppend<T>(string inputUri, string parentXPath,
            List<T> entities, bool appendToLast) where T : new()
        {
            if (!File.Exists(inputUri) || string.IsNullOrWhiteSpace(parentXPath)
                || entities == null || entities.Count == 0)
            {
                return false;
            }

            XmlDocument document = new XmlDocument();
            document.Load(inputUri);
            XmlElement parentElement = document.DocumentElement.SelectSingleNode(parentXPath) as XmlElement;

            if (parentElement == null)
            {
                return false;
            }

            string elementContent = ConvertToString<T>(entities);

            if (appendToLast)
            {
                parentElement.InnerXml += elementContent;
            }
            else
            {
                parentElement.InnerXml = elementContent;
            }

            document.Save(inputUri);
            document = null;

            return true;
        }
        /// <summary>
        /// 实体集合转换成XML字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entities"></param>
        /// <returns></returns>
        public static string ConvertToString<T>(List<T> entities) where T : new()
        {
            List<XElement> elements = Convert<T>(entities);
            if (elements == null || elements.Count == 0)
            {
                return string.Empty;
            }

            StringBuilder builder = new StringBuilder();
            elements.ForEach(p => builder.AppendLine(p.ToString()));

            return builder.ToString();
        }
        /// <summary>
        /// 实体集合转换成XElement集合
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entities"></param>
        /// <returns></returns>
        public static List<XElement> Convert<T>(List<T> entities) where T : new()
        {
            if (entities == null || entities.Count == 0)
            {
                return new List<XElement>();
            }

            List<XElement> elements = new List<XElement>();
            XElement element;

            foreach (var entity in entities)
            {
                element = Convert<T>(entity);
                if (element == null)
                {
                    continue;
                }

                elements.Add(element);
            }

            return elements;
        }

        /// <summary>
        /// 实体转换成XML字符串
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static string ConvertToString<T>(T entity) where T : new()
        {
            XElement element = Convert<T>(entity);
            return element == null ? string.Empty : element.ToString();
        }
        /// <summary>
        /// 实体转换成XElement
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public static XElement Convert<T>(T entity) where T : new()
        {
            if (entity == null)
            {
                return null;
            }
            string className = GetClassName<T>();
            XElement element = new XElement(className);
            Convert<T>(element, entity);
            return element;
        }


        private static void Convert<T>(XElement element, T entity) where T : new()
        {
            List<PropertyInfo> properties = entity.GetType().GetProperties().ToList();
            string propertyName = string.Empty;
            object propertyValue = null;
            foreach (PropertyInfo property in properties)
            {
                if (property.CanRead)
                {
                    propertyName = GetPropertyName(property);
                    propertyValue = property.GetValue(entity, null);
                    //
                    if (property.PropertyType.Namespace == "System")
                    {
                        //属性名为Value ,把值写到元素内容中
                        if (propertyName.Equals("Value", StringComparison.CurrentCultureIgnoreCase))
                            element.Value = propertyValue.ToString();
                        else
                            element.SetAttributeValue(propertyName, propertyValue);
                    }
                    else
                    {
                        XElement child = new XElement(propertyName);
                        //命名空间非System,属性可能是自定义封装类
                        Convert<dynamic>(child, propertyValue);
                        element.Add(child);
                    }
                }
            }

        }



        public static XElement ConvertBk<T>(T entity) where T : new()
        {
            if (entity == null)
            {
                return null;
            }

            string className = GetClassName<T>();
            XElement element = new XElement(className);

            List<PropertyInfo> properties = typeof(T).GetProperties().ToList();
            string propertyName = string.Empty;
            object propertyValue = null;



            foreach (PropertyInfo property in properties)
            {
                if (property.CanRead)
                {
                    propertyName = GetPropertyName(property);
                    propertyValue = property.GetValue(entity, null);
                    if (property.PropertyType.Namespace == "System")
                    {
                        element.SetAttributeValue(propertyName, propertyValue);
                    }
                    else
                    {
                        XElement xmlChild = new XElement(propertyName);
                        Type type = property.PropertyType;
                        var childList = type.GetProperties().ToList();

                        foreach (PropertyInfo child in childList)
                        {
                            if (child.CanRead)
                            {
                                propertyValue = child.GetValue(propertyValue, null);
                                xmlChild.SetAttributeValue(GetPropertyName(child), propertyValue);
                                element.Add(xmlChild);
                            }
                        }
                    }
                }
            }
            return element;
        }

        public static IList<T> ParseByDescendants<T>(string inputUri) where T : new()
        {
            if (!File.Exists(inputUri))
            {
                return new List<T>();
            }

            XDocument document = XDocument.Load(inputUri);

            return ParseByDescendants<T>(document);
        }

        public static IList<T> ParseByDescendants<T>(XDocument document) where T : new()
        {
            if (document == null)
            {
                return new List<T>();
            }

            string xName = GetClassName<T>();
            IEnumerable<XElement> elements = document.Descendants(xName);

            return ParseByDescendants<T>(elements);
        }

        public static IList<T> ParseByDescendants<T>(IEnumerable<XElement> elements) where T : new()
        {
            if (elements == null || elements.Count() == 0)
            {
                return new List<T>();
            }

            List<T> entities = new List<T>();

            foreach (XElement element in elements)
            {
                entities.Add(AddEntity<T>(element.Attributes()));
            }

            return entities;
        }

        public static T AddEntity<T>(IEnumerable<XAttribute> attributes) where T : new()
        {
            if (attributes == null || attributes.Count() == 0)
            {
                return default(T);
            }

            T entity = new T();
            List<PropertyInfo> properties = typeof(T).GetProperties().ToList();

            foreach (XAttribute attribute in attributes)
            {
                SetPropertyValue<T>(properties, entity, attribute.Name.ToString(), attribute.Value);
            }

            return entity;
        }

        public static IList<T> Parse<T>(string inputUri, string parentXPath) where T : new()
        {
            if (!File.Exists(inputUri) || string.IsNullOrWhiteSpace(parentXPath))
            {
                return new List<T>();
            }

            XmlDocument document = new XmlDocument();
            document.Load(inputUri);

            return Parse<T>(document, parentXPath);
        }

        public static IList<T> Parse<T>(XmlDocument document, string parentXPath) where T : new()
        {
            if (document == null || string.IsNullOrWhiteSpace(parentXPath))
            {
                return new List<T>();
            }

            XmlNode parentNode = document.DocumentElement.SelectSingleNode(parentXPath);

            if (parentNode == null)
            {
                return new List<T>();
            }

            return Parse<T>(parentNode);
        }

        public static IList<T> Parse<T>(XmlNode parentNode) where T : new()
        {
            if (parentNode == null || !parentNode.HasChildNodes)
            {
                return new List<T>();
            }

            XmlNodeList nodeList = parentNode.ChildNodes;

            return Parse<T>(nodeList);
        }

        public static IList<T> Parse<T>(XmlNodeList nodeList) where T : new()
        {
            if (nodeList == null || nodeList.Count == 0)
            {
                return new List<T>();
            }

            List<T> entities = new List<T>();
            AddEntities<T>(nodeList, entities);

            return entities;
        }

        public static IList<T> Parse<T>(string inputUri) where T : new()
        {
            if (!File.Exists(inputUri))
            {
                return new List<T>();
            }

            XmlReaderSettings settings = new XmlReaderSettings();
            settings.IgnoreComments = true;
            settings.IgnoreWhitespace = true;

            XmlReader reader = XmlReader.Create(inputUri, settings);

            return Parse<T>(reader);
        }

        public static IList<T> Parse<T>(XmlReader reader) where T : new()
        {
            if (reader == null)
            {
                return new List<T>();
            }

            reader.ReadStartElement();
            string className = GetClassName<T>();
            List<PropertyInfo> properties = typeof(T).GetProperties().ToList();
            List<T> entities = new List<T>();
            T entity = new T();

            while (!reader.EOF)
            {
                if (!string.Equals(reader.Name, className) || !reader.IsStartElement())
                {
                    reader.Read();
                    continue;
                }

                entity = new T();

                if (!reader.HasAttributes)
                {
                    entities.Add(entity);
                    reader.Read();
                    continue;
                }

                SetPropertyValue<T>(reader, properties, entity);
                entities.Add(entity);
                reader.Read();
            }

            reader.Close();

            return entities;
        }

        public static string GetClassName<T>() where T : new()
        {
            string className = typeof(T).Name;

            ClassAttribute[] attributes = typeof(T).GetCustomAttributes(
                typeof(ClassAttribute), false) as ClassAttribute[];

            if (attributes != null && attributes.Length > 0)
            {
                if (!string.IsNullOrWhiteSpace(attributes[0].Name))
                {
                    className = attributes[0].Name;
                }
            }

            return className;
        }

        public static string GetPropertyName(PropertyInfo property)
        {
            if (property == null)
            {
                return string.Empty;
            }

            string propertyName = property.Name;

            PropertyAttribute[] attributes = property.GetCustomAttributes(typeof(PropertyAttribute),
                false) as PropertyAttribute[];

            if (attributes != null && attributes.Length > 0)
            {
                if (!string.IsNullOrWhiteSpace(attributes[0].Name))
                {
                    propertyName = attributes[0].Name;
                }
            }

            return propertyName;
        }

        private static void AddEntities<T>(XmlNodeList nodeList,
            List<T> entities) where T : new()
        {
            string className = GetClassName<T>();
            List<PropertyInfo> properties = typeof(T).GetProperties().ToList();
            T entity = new T();

            foreach (XmlNode xmlNode in nodeList)
            {
                XmlElement element = xmlNode as XmlElement;
                if (element == null || !string.Equals(className, element.Name))
                {
                    continue;
                }

                entity = new T();
                if (!element.HasAttributes)
                {
                    entities.Add(entity);
                    continue;
                }

                XmlAttributeCollection attributes = element.Attributes;
                foreach (XmlAttribute attribute in attributes)
                {
                    SetPropertyValue<T>(properties, entity, attribute.Name, attribute.Value);
                }

                entities.Add(entity);
            }
        }

        private static void SetPropertyValue<T>(XmlReader reader,
            List<PropertyInfo> properties, T entity) where T : new()
        {
            while (reader.MoveToNextAttribute())
            {
                SetPropertyValue<T>(properties, entity, reader.Name, reader.Value);
            }
        }

        private static void SetPropertyValue<T>(List<PropertyInfo> properties,
            T entity, string name, string value) where T : new()
        {
            foreach (var property in properties)
            {
                if (!property.CanWrite)
                {
                    continue;
                }

                string propertyName = GetPropertyName(property);

                if (string.Equals(name, propertyName))
                {
                    FuncDictionary action = new FuncDictionary();
                    object invokeResult = action.DynamicInvoke(property.PropertyType, value);

                    property.SetValue(entity, invokeResult, null);
                }
            }
        }

    }
}

结果:

<Document TaskGuid="00000000-0000-0000-0000-000000000000" DataGuid="38726e0a-be8d-4937-ae8d-1444424c4e0a" DataType="QueryVehicleSearch" PageSize="20" PageIndex="3" Total="300" RequestTime="21:40:58" ReturnTime="21:43:58">
  <SortMethod Type="TEXT">Create</SortMethod>
  <OrderMethod Type="TEXT">asc</OrderMethod>
  <Data>
    <column Type="TEXT">id</column>
    <datatype Type="TEXT">int</datatype>
    <length Type="TEXT">10</length>
    <isnullable Type="TEXT" />
    <identity Type="TEXT" />
    <key Type="TEXT" />
    <defaults Type="TEXT" />
    <remark Type="TEXT">id</remark>
  </Data>
</Document>


转载:http://www.bianceng.cn/Programming/csharp/201311/38104_3.htm

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值