前言:

开发过程中经常需要返回某实体类的列表,公司通常用的都是XML格式的接口,小猪借鉴了公司前辈留下的代码一直是类似这么写的:

public static string GetXMLList(IList<Article> articlelist)
{
using (MemoryStream memoryStream = new MemoryStream())
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.NewLineChars = Environment.NewLine;
using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
{
xmlWriter.WriteStartDocument(true);
xmlWriter.WriteStartElement("Articles");
if (articlelist != null)
{
foreach (var article in articlelist)
{
xmlWriter.WriteStartElement("Article");
xmlWriter.WriteStartAttribute("id");
xmlWriter.WriteString(article.Id.ToString());
xmlWriter.WriteEndAttribute(); xmlWriter.WriteStartElement("Title");
xmlWriter.WriteCData(article.Title);
xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("Summary");
xmlWriter.WriteCData(article.Summary);
xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("Author");
xmlWriter.WriteCData(article.Author);
xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("CreateDate");
xmlWriter.WriteCData(article.CreateDate.ToString("yyyy-MM-dd"));
xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("BannerURL");
xmlWriter.WriteCData(article.BannerURL);
xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("ImageURL");
xmlWriter.WriteCData(article.ImageURL);
xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("ImageAuthor");
xmlWriter.WriteCData(article.ImageAuthor);
xmlWriter.WriteEndElement(); xmlWriter.WriteStartElement("Category");
xmlWriter.WriteCData(article.Category.ToString());
xmlWriter.WriteEndElement(); xmlWriter.WriteEndElement();
}
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
}
string xml = Encoding.UTF8.GetString(memoryStream.ToArray());
return xml;

}

生成的代码:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Articles>
<Article id="83">
<Title><![CDATA[存储]]></Title>
<Summary><![CDATA[asdsa]]></Summary>
<Author><![CDATA[asdsa]]></Author>
<CreateDate><![CDATA[2013-12-30]]></CreateDate>
<BannerURL><![CDATA[/Images/2013年12月/20131230153738573.png]]></BannerURL>
<ImageURL><![CDATA[/Images/2013年12月/20131230153731941.png]]></ImageURL>
<ImageAuthor><![CDATA[sda]]></ImageAuthor>
<Category><![CDATA[1]]></Category>
</Article>
<Article id="81">
<Title><![CDATA[存储]]></Title>
<Summary><![CDATA[asdsa]]></Summary>
<Author><![CDATA[asdsa]]></Author>
<CreateDate><![CDATA[2013-12-30]]></CreateDate>
<BannerURL><![CDATA[/Images/2013年12月/20131230153738573.png]]></BannerURL>
<ImageURL><![CDATA[/Images/2013年12月/20131230153731941.png]]></ImageURL>
<ImageAuthor><![CDATA[sda]]></ImageAuthor>
<Category><![CDATA[1]]></Category>
</Article>
</Articles>

代码一直延续到昨天!小猪决定重构他!

重构一:去除重复代码

首先上述代码最大的问题就是大量的复制粘贴,违背了DRY(Don't Repeated Yourself)原则。多个字段就要多粘贴一次,为了解决这个问题在遍历实体列表时使用下属代码:

using (MemoryStream memoryStream = new MemoryStream())
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.NewLineChars = Environment.NewLine;
using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
{
xmlWriter.WriteStartDocument(true);
xmlWriter.WriteStartElement("Articles");
if (articlelist != null)
{
foreach (var article in articlelist)
{
Type type = typeof(Article);
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
object ob = propertyInfo.GetValue(article, null);
if (null != ob)
{
xmlWriter.WriteStartElement(propertyInfo.Name);
xmlWriter.WriteCData(ob.ToString());
xmlWriter.WriteEndElement();
}
}
xmlWriter.WriteEndElement();
}
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
} string xml = Encoding.UTF8.GetString(memoryStream.ToArray());
return xml;
}

可是这样只能遍历Article类型,其他类型还是使用不了这个方法

重构二:加入泛型

在最原始的代码中每为一个实体增加类似功能的时候都要把那一整块代码复制过来然后做修改,我们在重构一中还是没有解决这个问题,为了使上面的方法能够在以后被重复利用我们加入泛型

public static string GetXMLList<T>(IList<T> articlelist)
{
using (MemoryStream memoryStream = new MemoryStream())
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.NewLineChars = Environment.NewLine;
using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
{
xmlWriter.WriteStartDocument(true);
xmlWriter.WriteStartElement("Roots");
Type type = typeof(T);
if (articlelist != null)
{
foreach (var article in articlelist)
{
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
object ob = propertyInfo.GetValue(article, null);
if (null != ob)
{
xmlWriter.WriteStartElement(propertyInfo.Name);
xmlWriter.WriteCData(ob.ToString());
xmlWriter.WriteEndElement();
}
}
xmlWriter.WriteEndElement();
}
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
} string xml = Encoding.UTF8.GetString(memoryStream.ToArray());
return xml;
}
}

这样代码完成了多类型的使用,但是却把所有的共有属性都写进了XML,在实际使用中我们可能不希望把所有属性都列进来,例如是否推荐字段,阅读权限字段等等~

重构三:

重构:...

...

重构N

为了使每个节点上面增加Id属性,定义一个抽象类Listable。抽象类中包涵自动Id,让需要提供列表的实体类继承至这个抽象类:

/*==========================================================
*作者:SmallerPig
*时间:2013/12/30 17:26:01
*版权所有:无锡睿阅数字科技有限公司
============================================================*/
namespace RY.Entity
{
public abstract class Listable
{
public int Id { get; set; }
}
}

实体类来继承它。例如:

public class Article : Listable
{
public string Title { get; set; } public string Summary { get; set; } }

然后给泛型方法加上约束,在该指定Id的地方加上id属性!

static string ToXML<T>(IList<T> TList, string ingor) where T : Listable
{
using (MemoryStream memoryStream = new MemoryStream())
{
XmlWriterSettings xmlWriterSettings = new XmlWriterSettings();
xmlWriterSettings.Indent = true;
xmlWriterSettings.Encoding = new UTF8Encoding(false);
xmlWriterSettings.NewLineChars = Environment.NewLine;
using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, xmlWriterSettings))
{
xmlWriter.WriteStartDocument(true);
xmlWriter.WriteStartElement("Roots");
if (TList != null)
{
​ Type type = typeof(T);
foreach (T t in TList)
{
xmlWriter.WriteStartElement(type.Name);
xmlWriter.WriteStartAttribute("id");
xmlWriter.WriteString(t.Id.ToString());
xmlWriter.WriteEndAttribute();
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
if (propertyInfo.CanRead && propertyInfo.Name.ToLower() != ingor.ToLower())
{
if (propertyInfo.PropertyType == typeof(DateTime))
{
xmlWriter.WriteStartElement(propertyInfo.Name);
DateTime dt = Convert.ToDateTime(propertyInfo.GetValue(t, null));
xmlWriter.WriteCData(dt.ToString("yyyy-MM-dd hh:mm:ss"));
xmlWriter.WriteEndElement();
}
if (propertyInfo.PropertyType == typeof(String) || propertyInfo.PropertyType == typeof(int))
{
object ob = propertyInfo.GetValue(t, null);
if (null != ob)
{
xmlWriter.WriteStartElement(propertyInfo.Name);
xmlWriter.WriteCData(ob.ToString());
xmlWriter.WriteEndElement();
}
}
}
}
xmlWriter.WriteEndElement();
}
}
xmlWriter.WriteEndElement();
xmlWriter.WriteEndDocument();
}
string xml = Encoding.UTF8.GetString(memoryStream.ToArray());
return xml;
}
}

最后效果:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<Roots>
<Article id="83">
<Title><![CDATA[存储]]></Title>
<Summary><![CDATA[asdsa]]></Summary>
<Author><![CDATA[asdsa]]></Author>
<Category><![CDATA[1]]></Category>
<CreateDate><![CDATA[2013-12-30 03:37:52]]></CreateDate>
<BannerURL><![CDATA[/Images/2013年12月/20131230153738573.png]]></BannerURL>
<ImageURL><![CDATA[/Images/2013年12月/20131230153731941.png]]></ImageURL>
<ImageAuthor><![CDATA[sda]]></ImageAuthor>
<Id><![CDATA[83]]></Id>
</Article>
<Article id="82">
<Title><![CDATA[存储]]></Title>
<Summary><![CDATA[asdsa]]></Summary>
<Author><![CDATA[asdsa]]></Author>
<Category><![CDATA[1]]></Category>
<CreateDate><![CDATA[2013-12-30 03:37:51]]></CreateDate>
<BannerURL><![CDATA[/Images/2013年12月/20131230153738573.png]]></BannerURL>
<ImageURL><![CDATA[/Images/2013年12月/20131230153731941.png]]></ImageURL>
<ImageAuthor><![CDATA[sda]]></ImageAuthor>
<Id><![CDATA[82]]></Id>
</Article>
</Roots>

使用反射来编写实体类的XML的更多相关文章

  1. 简单实体类和xml文件的相互转换

    最近写一个题目,要求将一组员工实体类转换成xml文件,或将xml文件转换成一组实体类.题目不难,但写完感觉可以利用泛型和反射将任意一个实体类和xml文件进行转换.于是今天下午立马动手 试了下,做了个简 ...

  2. 实体类转xml

    看项目中需要实体类转xml,大家是拼接的.感觉可以利用反射实现.于是写了下 代码如下 package com.kevin.util; import org.springframework.util.O ...

  3. 利用JAXB实现java实体类和xml互相转换

    1.应用场景 在使用WebService实现数据上传下载,数据查询时,可以利用JAXB实现java实体类和xml互相转换 2.Demo 2.1 student.java 实体类,包含list(set同 ...

  4. C#实体类生成XML与XML Schema文档

    一.实体类生成XML private void CreateXML() { Type[] objType = DBEntityRegst(); foreach (var item in objType ...

  5. 使用C#实现实体类和XML相互转换

    一.实体类转换成XML 将实体类转换成XML需要使用XmlSerializer类的Serialize方法,将实体类序列化 public static string XmlSerialize<T& ...

  6. Android利用反射机制为实体类属性赋值

    在做android项目时,有时会遇到从网络上获取json类型数据,赋值给实体类,实体类属性少可以一个一个的赋值,如果实体类有很多属性,赋值可能就要耗很长的功夫了,幸好Java给我们提供了反射机制.下面 ...

  7. 实现实体类和Xml相互转化

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.X ...

  8. 利用Java反射机制对实体类的常用操作工具类ObjectUtil

    代码: ObjectUtil类: import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.Simpl ...

  9. C#实体类与XML相互转换

    1.实体类与XML相互转换 将实体类转换成XML需要使用XmlSerializer类的Serialize方法,将实体类序列化. 把XML转换成相应的实体类,需要使用到XmlSerializer类的De ...

随机推荐

  1. 老笔记本_Win7_U盘_ReadyBoost

    老笔记本 Win7 U盘 ReadyBoost 值得尝试

  2. mysql 倒引号

    1.在mysql中,保留字不能作为表名,字段名等用处,如下:mysql> alter table student add column desc varchar(16) after name;1 ...

  3. java读取excel文件数据

    package com.smp.server.Ctrl; import java.io.File;import java.io.FileInputStream;import java.io.FileN ...

  4. vim的配置文件及常用的快捷键

    一些最简单的配置,即在.vimrc中可以写入的配置: 首先,说明一点,在.vimrc文件中,可以用“  把一行的配置注销掉. set nocompatible  “关闭 vi 兼容模式:其中 comp ...

  5. Binary Tree Paths

    Description: Given a binary tree, return all root-to-leaf paths. For example, given the following bi ...

  6. embed object以及video标签的区别以及使用

    embed object以及video标签的区别以及使用?

  7. PO BO VO DTO POJO DAO 概念及其作用

    PO BO VO DTO POJO DAO 概念及其作用(附转换图) 博客分类: java javadaovopojobo        J2EE开发中大量的专业缩略语很是让人迷惑, 特别是对于刚毕业 ...

  8. Eclipse下导入外部jar包的3种方式 (zhuan)

    http://blog.csdn.net/mazhaojuan/article/details/21403717 ******************************************* ...

  9. Python标准库06 子进程 (subprocess包)

    这里的内容以Linux进程基础和Linux文本流为基础.subprocess包主要功能是执行外部的命令和程序.比如说,我需要使用wget下载文件.我在Python中调用wget程序.从这个意义上来说, ...

  10. aliyun CentOS6.5 上 svn 安装笔记

    为了方便管理自己的一些学习资料.总结等,在CentOS6.5上安装SVN,记录过程如下: 1.1  安装方式  独立服务器  fsfs SVN服务器有2种运行方式:独立安装.SVN+Apache.独立 ...