C#实体映射XML操作

在我的项目有一些xml数据(格式如下)

代码
 1 <?xml version="1.0" encoding="utf-8"?>
 2 <Config>
 3   <FeatureType>
 4     <Item ID="1" Name="外型材质" Image="外型材质特征用到的图片" Order="2" />
 5     <Item ID="2" Name="拍照功能" Image="特征用到的图片" Order="2" />
 6   </FeatureType>
 7   <OSType>
 8     <Item ID="1" Name="Windows Mobile Professional" />
 9     <Item ID="2" Name="Windows Mobile Standard" />
10     <Item ID="3" Name="Linux" />
11     <Item ID="4" Name="其它" />
12     <Item ID="5" Name="Andriod" />
13   </OSType>
14 </Config>

以前的处理方式是这样:

1.建立相应实体类

例:类FeatureType对应一个FeatureType结点下一个实体

public class FeatureType
{
    
public int ID { getset; }
    
public string Name { getset; }
}

2.写一个FeatureType的管理类来处理如(添加,删除,更新,取列表,取单个)等操作

     这样问题就来了:如果是少量的xml文档或结点组(例如<FeatureType>,<OSType>),处理起来还算轻松,可现在有很多这样的文档或结点组,而且我还想以强类型实体的形式来访问处理..........那就写吧。

我的处理方法是这样的,欢迎大家指正!

首先需要两个特性类:

CacheEntityAttribute
[AttributeUsage(AttributeTargets.Class,AllowMultiple=false,Inherited=true)] 
    
public class CacheEntityAttribute : Attribute
    {
        
//public string ConfigPath { get; set; }
        public string SectionName { getset; }
        
public string ElementName { getset; }

        
public CacheEntityAttribute(string sectionName, string elementName)
        {
            
//this.ConfigPath = configPath;
            this.SectionName = sectionName;
            
this.ElementName = elementName;
        }
    }
CacheEntityPropertyAttribute
[AttributeUsage(AttributeTargets.Property,AllowMultiple=false,Inherited=true)]
    
public class CacheEntityPropertyAttribute : Attribute
    {
        
public string PropertyName { getset; }
        
public Type DateType { getset; }
        
public bool IsPrimaryKey { getset; }

        
public CacheEntityPropertyAttribute(string propertyName, Type dataType,bool isPrimaryKey)
        {
            
this.PropertyName = propertyName;
            
this.DateType = dataType;
            
this.IsPrimaryKey = isPrimaryKey;
        }

        
public CacheEntityPropertyAttribute(string propertyName, Type dataType) :
            
this(propertyName,dataType,false)
        {}
    }

CacheEntityAttribute:描述实体类对应的结点名称及要处理的xml原素名称(应用于类)

CacheEntityPropertyAttribute:描述实体字段对应的xml结点属性信息(应用于属性)

 实体基类:

CacheEntityBase
public abstract class CacheEntityBase
    {
        [CacheEntityProperty(
"ID"typeof(int),true)]
        
public int ID { getset; }

        [CacheEntityProperty(
"Name"typeof(string),true)]
        
public string Name { getset; }
    }

新的FeatureType类

FeatureType
[CacheEntity("FeatureType""Item")]
    
public class FeatureType : CacheEntityBase
    {
        [CacheEntityProperty(
"Image",typeof(string))]
        
public string Image { getset; }

        [CacheEntityProperty(
"Order",typeof(int))]
        
public int Order { getset; }

        
public FeatureType(int id, string name, string image, int order)
        {
            
this.ID = id;
            
this.Name = name;
            
this.Image = image;
            
this.Order = order;
        }

        
public FeatureType() { }
    }

 CacheEntityManager类:

这个类型中有一些范型方法(如,更新,添加等),核心就是通过反射来处理相关操作

CacheEntityManager
public class CacheEntityManager
    {
        
public string ConfigPath { getset; }
        
private XmlDocument xdt;
        
public string RootElement { getset; }

        
public CacheEntityManager(string configPath,string rootElement)
        {
            
this.ConfigPath = configPath;
            
this.RootElement = rootElement;
            
this.xdt = new XmlDocument();
            
this.xdt.Load(ConfigPath);
        }

        
/// <summary>
        
/// 根据ID,加载单个实体
        
/// </summary>
        
/// <typeparam name="T"></typeparam>
        
/// <param name="id"></param>
        
/// <returns></returns>
        public T LoadSingle<T>(int id) where T : CacheEntityBase
        {
            CacheEntityAttribute eAttr 
=
                TypeHelper.LoadLastAttribute
<CacheEntityAttribute>(typeof(T), true);
            
string xpath = "/" + this.RootElement + "/" + eAttr.SectionName + "/" + eAttr.ElementName;
            xpath 
+= "[@ID=" + id.ToString() + "]";
            
            XmlNode node 
= this.xdt.SelectSingleNode(xpath);
            
return createInstance<T>(node);
            
        }

        
public void Remove<T>(int id) where T : CacheEntityBase
        {
            CacheEntityAttribute eAttr 
= 
                TypeHelper.LoadLastAttribute
<CacheEntityAttribute>(typeof(T), true);
            
string xpath = "/" + this.RootElement + "/" + eAttr.SectionName + "/" + eAttr.ElementName;
            xpath 
+= "[@ID=" + id.ToString() + "]";
            XmlNodeList nodeList 
= this.xdt.SelectNodes(xpath);
            
if (nodeList.Count > 0)
            {
                
for (int i = 0; i < nodeList.Count; i++)
                {
                    nodeList[i].ParentNode.RemoveChild(nodeList[i]);
                }
                
this.xdt.Save(this.ConfigPath);
            }
        }

        
private T createInstance<T>(XmlNode node)
        {
            
if (node == null)
            {
                
return default(T);
            }
            
else
            {
                List
<CacheEntityPropertyAttribute> attrs =
                    TypeHelper.LoadPropertyAttribute
<CacheEntityPropertyAttribute>(typeof(T));
                
                T obj 
= (T)Activator.CreateInstance<T>();
                Type objType 
= typeof(T);
                
for (int i = 0; i < attrs.Count; i++)
                {
                    XmlAttribute xmlAttr 
= getAttribute(node, attrs[i].PropertyName);
                    
try
                    {              
                        Type fType 
= attrs[i].DateType;
                        
object value;
                        
if (fType.IsValueType)
                        {
                            value 
= TypeHelper.Parse(fType, xmlAttr.Value);
                        }
                        
else
                        {
                            value 
= xmlAttr.Value;
                        }
                        objType.GetProperty(attrs[i].PropertyName).SetValue(obj,
                            value,
null);
                    }
                    
catch{}
                }
                
return obj;
            }
        }

        
private XmlAttribute getAttribute(XmlNode node,string attrName)
        {
            
try
            {
                
return node.Attributes[attrName];
            }
            
catch
            {
                
return null;
            }
        }

        
/// <summary>
        
/// 加载全部
        
/// </summary>
        
/// <param name="filter"></param>
        
/// <returns></returns>
        public List<T> LoadList<T>() where T : CacheEntityBase
        {
            List
<T> list = new List<T>();
            CacheEntityAttribute eAttr 
=
                AttributeHelper.LoadLastAttribute
<CacheEntityAttribute>(typeof(T), true);
            
string xpath = "/" + this.RootElement + "/" + eAttr.SectionName + "/" + eAttr.ElementName;
            XmlNodeList nodes 
= this.xdt.SelectNodes(xpath);
            
foreach (XmlNode node in nodes)
            {
                T obj 
= this.createInstance<T>(node);
                
if (obj != null) list.Add(obj);
            }
            
return list;
        }

        
/// <summary>
        
/// 持久化
        
/// </summary>
        
/// <typeparam name="T"></typeparam>
        
/// <param name="entity"></param>
        public void Insert<T>(T entity) where T : CacheEntityBase
        {
            CacheEntityAttribute eAttr 
=
                AttributeHelper.LoadLastAttribute
<CacheEntityAttribute>(typeof(T), true);
            List
<CacheEntityPropertyAttribute> attrs =
                    TypeHelper.LoadPropertyAttribute
<CacheEntityPropertyAttribute>(typeof(T));
            
string xpath = "/" + this.RootElement + "/" + eAttr.SectionName + "/" + eAttr.ElementName;
            
string temp = xpath + "[@Name='" + TypeHelper.GetPropertyValue(entity, "Name"+ "']/@Name";
            XmlNode n 
= this.xdt.SelectSingleNode(temp);

            
if (n != nullreturn;
            XmlElement elm 
= this.xdt.CreateElement(eAttr.ElementName);
            
foreach (CacheEntityPropertyAttribute attr in attrs)
            {
                XmlAttribute xa 
= this.xdt.CreateAttribute(attr.PropertyName);
                xa.Value 
= TypeHelper.GetPropertyValue(entity, attr.PropertyName).ToString();
                elm.Attributes.Append(xa);
            }
            
this.xdt.SelectSingleNode("/" + this.RootElement + "/" + eAttr.SectionName).AppendChild(elm);
            
this.xdt.Save(this.ConfigPath);
        }

        
/// <summary>
        
/// 更新
        
/// </summary>
        
/// <typeparam name="T"></typeparam>
        
/// <param name="entity"></param>
        public void Update<T>(T entity) where T : CacheEntityBase
        {
            CacheEntityAttribute eAttr 
=
                AttributeHelper.LoadLastAttribute
<CacheEntityAttribute>(typeof(T), true);
            List
<CacheEntityPropertyAttribute> attrs =
                    TypeHelper.LoadPropertyAttribute
<CacheEntityPropertyAttribute>(typeof(T));
            
string xpath = "/" + this.RootElement + "/" + eAttr.SectionName ;
            
string temp = xpath + "/" + eAttr.ElementName +
                
"[@Name='" + TypeHelper.GetPropertyValue(entity, "Name").ToString() + "'][@ID!=" +
                TypeHelper.GetPropertyValue(entity, 
"ID").ToString() + "]/@Name";
            XmlNode n 
= this.xdt.SelectSingleNode(temp);
            
if (n != nullreturn;
            xpath 
+= "/" + eAttr.ElementName + "[@ID=" + TypeHelper.GetPropertyValue(entity, "ID"+ "]";
            
string str2;
            
foreach (CacheEntityPropertyAttribute attr in attrs)
            {
                str2 
= xpath + "/@" + attr.PropertyName;
                XmlNode node 
= this.xdt.SelectSingleNode(str2);
                node.InnerText 
= TypeHelper.GetPropertyValue(entity, attr.PropertyName).ToString();
                
this.xdt.Save(this.ConfigPath);
            }

        }

    }

这个类还有一些问题没有处理,就是对主键的处理,相关的条件判断我是直接在类里面,需要后续版本会做相应处理.

首先不管理处理的好坏,感觉自已对反射的认识更深了一步!

还有就是处理String To ValueType类型时想了好久也没有解决办法,最后还是google了,原来可以Relection值类型的静态方法(Parse),哈哈,晕了半天

文章写的烂,您凑合着看!不爽请拍砖!

原文地址:https://www.cnblogs.com/byxxw/p/1644256.html