Xml匹配为对象集合(两种不同的方式)

一、前言

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

二、类图设计

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

 

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

PropertyAttribute、ClassAttribute、StringExtension、FuncDictionary的作用详见XmlAttribute与实体的转换和匹配方案(附源码)

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),  falseas 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                  falseas 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>

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值