博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Xml匹配为对象集合(两种不同的方式)
阅读量:6906 次
发布时间:2019-06-27

本文共 7243 字,大约阅读时间需要 24 分钟。

一、前言

上一篇随笔主要将实体转换成相应的Xml或者Xml对象,未考虑到属性的Attribute特性,以后有时间再整理一下。本文中的Xml匹配涉及到类的特性和属性的特性,并且对该类的匹配进行了相应的优化,尽量将反射引起的性能问题降低最低(其实,对于对象数量不是很多的Xml匹配,性能是可以忽略不计的)。

二、类图设计

 主要思路为:通过反射将与类名的节点匹配,然后匹配属性(属性特性名称或者属性名称)值,设计图如下所示:

 

类图中各个类的作用如下:

PropertyAttribute、ClassAttribute、StringExtension、FuncDictionary的作用详见。

AttributeUtility主要用于获取类名和属性名称。
ReflectionUtility主要用于获取类型的属性对象与属性对应的特性名称的字典,为匹配进行优化处理。
XmlParser主要用于匹配Xml为实体对象。

 

三、具体实现

3.1 ReflectionUtility

该类主要用于获取某个类型的特性名称和相应的属性对象的字典。返回的类型为Dictionary<string, PropertyInfo>,其中Key为属性的特性名称,而非属性名称,Vaule为对应的属性对象。如此设计,主要是方便后续的操作。

主要方法为:
public static Dictionary<string, PropertyInfo> GetPropertyMapperDictionary<T>() where T : new(),
public static Dictionary<string, PropertyInfo> GetPropertyMapperDictionary(Type type) ,代码如下:
 1     
public 
class ReflectionUtility
 2     {
 3         
public 
static Dictionary<
string, PropertyInfo> GetPropertyMapperDictionary<T>() 
where T : 
new()
 4         {
 5             
return GetPropertyMapperDictionary(
typeof(T));
 6         }
 7 
 8         
public 
static Dictionary<
string, PropertyInfo> GetPropertyMapperDictionary(Type type) 
 9         {
10             
if (type == 
null)
11             {
12                 
return 
null;
13             }
14 
15             List<PropertyInfo> properties = type.GetProperties().ToList();
16             
var nameMapperDic = 
new Dictionary<
string, PropertyInfo>();
17             
string propertyAttributeName = 
null;
18 
19             
foreach (PropertyInfo property 
in properties)
20             {
21                 propertyAttributeName = AttributeUtility.GetPropertyName(property);
22                 nameMapperDic.Add(propertyAttributeName, property);
23             }
24 
25             
return nameMapperDic;
26         }
27 
28         
public 
static IList<
string> GetPropertyNames<T>() 
where T : 
new()
29         {
30             List<PropertyInfo> properties = 
typeof(T).GetProperties().ToList();
31             
var propertyNames = 
new List<
string>();
32 
33             
foreach (PropertyInfo property 
in properties)
34             {
35                 propertyNames.Add(AttributeUtility.GetPropertyName(property));
36             }
37 
38             
return propertyNames;
39         }
40     }

 

3.2 AttributeUtility

该类主要用于获取某个类型的类的特性名称和属性的特性名称。如果类的特性不存在,则返回类名。如果属性的特性名称不存在,则返回属性的名称。

主要方法为:
public static string GetClassName<T>() where T : new(),
public static string GetClassName(Type type) ,
public static string GetPropertyName(PropertyInfo property) ,代码如下:
 1     
public 
class AttributeUtility
 2     {
 3         
public 
static 
string GetClassName<T>() 
where T : 
new()
 4         {
 5             
return GetClassName(
typeof(T));
 6         }
 7 
 8         
public 
static 
string GetClassName(Type type) 
 9         {
10             
if (type == 
null)
11             {
12                 
return 
string.Empty;
13             }
14 
15             
string className = type.Name;
16             ClassAttribute[] attributes = type.GetCustomAttributes(
17                 
typeof(ClassAttribute), 
false
as ClassAttribute[];
18 
19             
if (attributes != 
null && attributes.Length > 
0)
20             {
21                 
if (!
string.IsNullOrWhiteSpace(attributes[
0].Name))
22                 {
23                     className = attributes[
0].Name;
24                 }
25             }
26 
27             
return className;
28         }
29 
30         
public 
static 
string GetPropertyName(PropertyInfo property)
31         {
32             
if (property == 
null)
33             {
34                 
return 
string.Empty;
35             }
36 
37             
string propertyName = property.Name;
38 
39             PropertyAttribute[] attributes = property.GetCustomAttributes(
typeof(PropertyAttribute),
40                 
false
as PropertyAttribute[];
41 
42             
if (attributes != 
null && attributes.Length > 
0)
43             {
44                 
if (!
string.IsNullOrWhiteSpace(attributes[
0].Name))
45                 {
46                     propertyName = attributes[
0].Name;
47                 }
48             }
49 
50             
return propertyName;
51         }
52     }

 

3.2 XmlParser

该类主要通过两种不同的方式匹配Xml为实体对象集合,一种直接通过XmlReader进行只进读取匹配,另外一种通过XElement进行相应的匹配。

主要方法为:
public static IList<T> Parse<T>(string xmlContent) where T : new(),
public static IList<T> Parse<T>(XDocument document) where T : new() ,
public static IList<T> Parse<T>(IEnumerable<XElement> elements) where T : new(),
public static IList<T> Parse<T>(XmlReader xmlReader) where T : new() ,代码如下:
  1     
public 
class XmlParser
  2     {
  3         
public 
static IList<T> Parse<T>(
string xmlContent) 
where T : 
new()
  4         {
  5             
try
  6             {
  7                 
if (
string.IsNullOrWhiteSpace(xmlContent))
  8                 {
  9                     
return 
new List<T>();
 10                 }
 11 
 12                 
using (StringReader reader = 
new StringReader(xmlContent))
 13                 {
 14                     
return Parse<T>(XmlReader.Create(reader));
 15                 }
 16             }
 17             
catch
 18             {
 19                 
return 
new List<T>();
 20             }
 21         }
 22 
 23         
public 
static IList<T> Parse<T>(XDocument document) 
where T : 
new()
 24         {
 25             
if (document == 
null)
 26             {
 27                 
return 
new List<T>();
 28             }
 29 
 30             
string className = AttributeUtility.GetClassName<T>();
 31             IEnumerable<XElement> elements = document.Root.Elements(className);
 32 
 33             
return Parse<T>(elements);
 34         }
 35 
 36         
public 
static IList<T> Parse<T>(IEnumerable<XElement> elements) 
where T : 
new()
 37         {
 38             
if (elements == 
null || elements.Count() == 
0)
 39             {
 40                 
return 
new List<T>();
 41             }
 42 
 43             
try
 44             {
 45                 
var propertyDic = ReflectionUtility.GetPropertyMapperDictionary<T>();
 46                 List<T> entities = 
new List<T>();
 47                 IEnumerable<XElement> innerElements = 
null;
 48                 T entity = 
new T();
 49 
 50                 
foreach (XElement element 
in elements)
 51                 {
 52                     entity = 
new T();
 53                     entities.Add(entity);
 54                     innerElements = element.Elements();
 55 
 56                     
foreach (XElement innerElement 
in innerElements)
 57                     {
 58                         SetPropertyValue<T>(propertyDic, entity, innerElement.Name.ToString(), innerElement.Value);
 59                     }
 60                 }
 61 
 62                 
return entities;
 63             }
 64             
catch
 65             {
 66                 
return 
new List<T>();
 67             }
 68         }
 69 
 70         
public 
static IList<T> Parse<T>(XmlReader xmlReader) 
where T : 
new()
 71         {
 72             
try
 73             {
 74                 
if (xmlReader == 
null)
 75                 {
 76                     
return 
new List<T>();
 77                 }
 78 
 79                 
return ParseXmlReader<T>(xmlReader);
 80             }
 81             
catch
 82             {
 83                 
return 
new List<T>();
 84             }
 85         }
 86 
 87         
private 
static IList<T> ParseXmlReader<T>(XmlReader xmlReader) 
where T : 
new()
 88         {
 89             List<PropertyInfo> properties = 
new List<PropertyInfo>(
typeof(T).GetProperties());
 90             
var propertyDic = ReflectionUtility.GetPropertyMapperDictionary<T>();
 91             
string className = AttributeUtility.GetClassName<T>();
 92             IList<T> entities = 
new List<T>();
 93             T entity = 
new T();
 94             
string lastElementName = 
null;
 95 
 96             
while (xmlReader.Read())
 97             {
 98                 
switch (xmlReader.NodeType)
 99                 {
100                     
case XmlNodeType.Element:
101                         
if (
string.Equals(xmlReader.Name, className))
102                         {
103                             entity = 
new T();
104                             entities.Add(entity);
105                         }
106                         lastElementName = xmlReader.Name;
107                         
break;
108                     
case XmlNodeType.Text:
109                         SetPropertyValue<T>(propertyDic, entity, lastElementName, xmlReader.Value);
110                         
break;
111                     
default:
112                         
break;
113                 }
114             }
115 
116             
return entities;
117         }
118 
119         
private 
static 
void SetPropertyValue<T>(Dictionary<
string, PropertyInfo> propertyDic, T entity, 
string lastElementName, 
string value) 
where T : 
new()
120         {
121             
if (!
string.IsNullOrWhiteSpace(lastElementName) && propertyDic.ContainsKey(lastElementName))
122             {
123                 PropertyInfo currentProperty = propertyDic[lastElementName];
124                 
if (currentProperty != 
null && currentProperty.CanWrite)
125                 {
126                     
object invokeResult = 
new FuncDictionary().DynamicInvoke(currentProperty.PropertyType, value);
127                     currentProperty.SetValue(entity, invokeResult, 
null);
128                 }
129             }
130         }
131     }

 

以上两种不同的方式匹配Xml,都是通过var propertyDic = ReflectionUtility.GetPropertyMapperDictionary<T>();来对反射所引起的性能进行了相关的优化。对于多个实体的匹配,只需要执行一次映射获取到属性特性的名称与对应属性的字典,其后的匹配以该字典来进行操作。

 

、总结

与上一篇随笔将对象集合转换为Xml恰恰相反,对于如下类似格式的Xml:

ExpandedBlockStart.gif
View Code
<MapperInfoItem>
  <DefaultName>MapperInfoItemIndex0</DefaultName>
  <CreatedTime>
2012/
1/
6 
19:
24:
34</CreatedTime>
  <IsActive>True</IsActive>
  <DefaultValue>
10</DefaultValue>
  <Percent>
27</Percent>
  <TargetUrl>www.codeplex.com?Id=
0</TargetUrl>
</MapperInfoItem>

本文中以上的代码完全能够对其进行相应的匹配。只不过上一篇随笔中未对类的特性名称和属性的特性名称进行考虑罢了,以后有时间再贴上改进后的代码。

转载地址:http://ilrdl.baihongyu.com/

你可能感兴趣的文章
corosync+pacemaker+crm实现drbd高可用
查看>>
Git Fork和PullRequest
查看>>
springBoot2.x设置quartz的overwriteExistingJobs参数
查看>>
VMware中通过克隆的Centos7,网卡突然没了
查看>>
学习笔记 DNS 子域授权 view
查看>>
stat函数
查看>>
在MyEclipse中部署项目到Tomcat服务器
查看>>
Kendo UI常用示例汇总(二十二)
查看>>
lnmp+coreseek实现站内全文检索(安装篇)
查看>>
六月技术指标和个人指标
查看>>
我的友情链接
查看>>
dojo layout
查看>>
初探 ELK - 每天5分钟玩转 Docker 容器技术(89)
查看>>
c#通过创建Windows服务启动程序
查看>>
系统架构设计指南
查看>>
我的友情链接
查看>>
Jquery Ajax方法传值到action
查看>>
亚马逊图书推荐--我感兴趣的
查看>>
Xmanager连接Centos6.3的远程桌面
查看>>
Office365:客户端升级后无法启动Microsoft Outlook
查看>>