前言:

开发过程中经常需要返回某实体类的列表,公司通常用的都是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. iOS - OC NSEnumerator 迭代器

    前言 @interface NSEnumerator<ObjectType> : NSObject <NSFastEnumeration> Xcode 7 对系统中常用的一系列 ...

  2. [转载] C++ STL string的Copy-On-Write技术

    原文: http://coolshell.cn/articles/12199.html stl的string是经过严格优化的, 深入理解对以后编程过程中应用string非常有益处, 感谢左耳朵耗子的精 ...

  3. linux rwxrwxrwt文件夹属性

    /tmp 的permission是rwxrwxrwt chmod 0777 /abc       rwxrwxrwx chmod  777 /abc        rwxrwxrwx chmod 17 ...

  4. Java源码初学_ArrayList

    一.ArrayList的构造器和构造方法 在ArrayList中定义了两个空数组,分别对应当指定默认构造方法时候,指向的数组已经给定容量,但是容量等于0的时候,指向的数组.此外在构造函数中传入Coll ...

  5. JavaSE复习_11 IO流复习

    △FileReader是使用默认码表读取文件, 如果需要使用指定码表读取, 那么可以使用InputStreamReader(字节流,编码表)    FileWriter是使用默认码表写出文件, 如果需 ...

  6. UIButton的状态

    normal(普通状态) 默认情况(Default) 对应的枚举常量:UIControlStateNormal highlighted(高亮状态)按钮被按下去的时候(手指还未松开)对应的枚举常量:UI ...

  7. iOS项目中的version和build

    Version在plist文件中的key是“CFBundleShortVersionString”,标识应用程序的发布版本号,和AppStore上的版本号保持一致.该版本的版本号是三个分隔的整数组成的 ...

  8. 将spring管理的bean使用注解的方式注入到servlet中

    Filter和Servlet中不能直接注解使用spring的bean,因为这两个都是servlet容器维护管理的,当然也有实现方法,如下: 1.创建一个AbstractServlet 抽象类,让你的所 ...

  9. C#_拆箱跟装箱

    Net的类型分为两种,一种是值类型,另一种是引用类型.这两个类型的本质区别,值类型数据是分配在栈中,而引用类型数据分配在堆上.那么如果要把一个值类型数据放到堆上,就需要装箱操作:反之,把一个放在堆上的 ...

  10. JavaScript 返回值

    Window.Open()返回值: 利用window.open(‘NewWindow.html’):打开新的窗口NewWindow.html后,如果有返回值需要处理,应通过window.opener. ...