在我的项目有一些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>
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 { get; set; }
public string Name { get; set; }
}
{
public int ID { get; set; }
public string Name { get; set; }
}
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 { get; set; }
public string ElementName { get; set; }
public CacheEntityAttribute(string sectionName, string elementName)
{
//this.ConfigPath = configPath;
this.SectionName = sectionName;
this.ElementName = elementName;
}
}
public class CacheEntityAttribute : Attribute
{
//public string ConfigPath { get; set; }
public string SectionName { get; set; }
public string ElementName { get; set; }
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 { get; set; }
public Type DateType { get; set; }
public bool IsPrimaryKey { get; set; }
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)
{}
}
public class CacheEntityPropertyAttribute : Attribute
{
public string PropertyName { get; set; }
public Type DateType { get; set; }
public bool IsPrimaryKey { get; set; }
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 { get; set; }
[CacheEntityProperty("Name", typeof(string),true)]
public string Name { get; set; }
}
{
[CacheEntityProperty("ID", typeof(int),true)]
public int ID { get; set; }
[CacheEntityProperty("Name", typeof(string),true)]
public string Name { get; set; }
}
新的FeatureType类
FeatureType
[CacheEntity("FeatureType", "Item")]
public class FeatureType : CacheEntityBase
{
[CacheEntityProperty("Image",typeof(string))]
public string Image { get; set; }
[CacheEntityProperty("Order",typeof(int))]
public int Order { get; set; }
public FeatureType(int id, string name, string image, int order)
{
this.ID = id;
this.Name = name;
this.Image = image;
this.Order = order;
}
public FeatureType() { }
}
public class FeatureType : CacheEntityBase
{
[CacheEntityProperty("Image",typeof(string))]
public string Image { get; set; }
[CacheEntityProperty("Order",typeof(int))]
public int Order { get; set; }
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 { get; set; }
private XmlDocument xdt;
public string RootElement { get; set; }
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 != null) return;
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 != null) return;
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);
}
}
}
{
public string ConfigPath { get; set; }
private XmlDocument xdt;
public string RootElement { get; set; }
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 != null) return;
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 != null) return;
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),哈哈,晕了半天
文章写的烂,您凑合着看!不爽请拍砖!