使用反射来编写实体类的XML

时间:2022-05-31 11:48:45

前言:

开发过程中经常需要返回某实体类的列表,公司通常用的都是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&num;实体类生成XML与XML Schema文档

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

  5. 使用C&num;实现实体类和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&num;实体类与XML相互转换

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

随机推荐

  1. UVA 1401 Remember the Word

    字典树优化DP                                Remember the Word Time Limit: 3000MS   Memory Limit: Unknown ...

  2. ios7 苹果原生二维码扫描(和微信类似)

    在ios7苹果推出了二维码扫描,以前想要做二维码扫描,只能通过第三方ZBar与ZXing. ZBar在扫描的灵敏度上,和内存的使用上相对于ZXing上都是较优的,但是对于 “圆角二维码” 的扫描确很困 ...

  3. Codeforces 57C Array dp暴力找到规律

    主题链接:点击打开链接 的非增量程序首先,计算, 如果不增加的节目数量x, 非减少一些方案是x 答案就是 2*x - n 仅仅需求得x就可以. 能够先写个n3的dp,然后发现规律是 C(n-1, 2* ...

  4. Node&plus;mongodb线上部署到阿里云

    Node+mongodb线上部署到阿里云 部署使用的主要工具是pm2+nginx,使用码云的私有仓库,自动部署到服务器,私有仓库和服务器要事先设置好免密码登录.使用DNSPOD进行域名解析.事先准备好 ...

  5. Flume环境搭建&lowbar;五种案例

    Flume环境搭建_五种案例 http://flume.apache.org/FlumeUserGuide.html A simple example Here, we give an example ...

  6. &lbrack;Swift&rsqb;LeetCode905&period; 按奇偶排序数组 &vert; Sort Array By Parity

    Given an array A of non-negative integers, return an array consisting of all the even elements of A, ...

  7. ubuntu16&period;04微信安装

    1.下载: git clone https://github.com/geeeeeeeeek/electronic-wechat/releases 2.移动微信客户端(下载解压重命名为wechat)到 ...

  8. ubuntu下pyspark的安装

    1.安装jkd1.8(这里不再描述) 2.直接在终端输入pip install pyspark(官网提供的最简单的一种安装方式) 过程如下: Collecting pyspark Downloadin ...

  9. JSP中使用Spring注入的Bean时需要注意的地方

    遇到问题 遇到一个问题:在JSP中,使用Spring注入的Bean对象时,未能正确地获取到想要的对象. 郁闷的是,它也没报错. 研究问题 使用DEBUG功能(好久不在JSP里写Java代码了,都忘了J ...

  10. 【图文教程】WebStorm下使用Github下载以及上传代码

    1.从一个git路径下,下载代码到本地,选择VCS->Checkout from Version Control ->GitHub.        2.可能会弹出需要设置上传代码的密码,这 ...