前言:

开发过程中经常需要返回某实体类的列表,公司通常用的都是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. 一个CSS中Z-index的用法

    一个CSS中Z-index的用法 CSS教程:彻底掌握Z-index属性     大多数的CSS属性都很容易使用.常常,当您对标记语言的元素使用CSS属性时,产生的结果会随着您刷新页面而立即呈现.而另 ...

  2. jquery 跳转到当前页面指定位置

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. C++中关于new及内存地址的思考

    OJ题刷多了,每次都是直接分配内存,那么,你还记得怎么动态分配内存吗? ———————————————————————————————————— 我们知道,使用malloc/calloc等分配内存的函 ...

  4. (十一)C语言中内存堆和栈的区别

    在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到.但对于很多的初学着来说,堆栈是一个很模糊的概念. 堆栈:一种数据结构.一个在程序运行时用于存放的地方,这可能是很多初学者的认 ...

  5. iOS之Scanning的实现

    http://i.cnblogs.com/EditPosts.aspx?postid=5288517 //写在最前 /* AVFoundation原生框架的好处就是扫描特别快效率特别高,但是可能会遇到 ...

  6. Windows 上远程访问 Unix 的 XWindow / XManager / X

    准备 下载 putty  - http://www.putty.org/ 安装 cygwin - http://cygwin.com/, 并添加 e.g. c:/cygwin/bin 到 Window ...

  7. opencl初探-sobel检测

    sobel检测的C版本,neon和GPU的时间比较. Platform: LG G3, Adreno 330 ,img size 3264x2448 sobel: C code neon GPU 73 ...

  8. 【MRPT】【icp-slam-live】Vs2013+ cmake3.6.1 + mrpt1.4.0+opencv2.9.4+wxWidget3.0.2环境配置

    Win10下Vs2013 + cmake3.6.1 + mrpt1.4.0+opencv2.9.4+wxWidget3.1.0环境配置 所接触过的最令我崩溃的环境配置.之前没有考虑到vs2013 20 ...

  9. redis+tomcat+nginx session共享

    http://www.cnblogs.com/zhrxidian/p/5432886.html系列课程 简洁明了 http://blog.csdn.net/grhlove123/article/det ...

  10. jmeter 构建一个Web测试计划

    添加用户 第一步你想做的每一个JMeter测试计划是添加一个 线程组 元素. 线程组告诉 JMeter的用户数量你想模拟,用户应该发送的次数 请求,请求他们应该送多少. 继续添加ThreadGroup ...