最近一项目中用XML进行数据交互,有一些(多个)不完全相同的XML文档,同样代表不同的数据,即我们在发送,接收时都是一个XML格式字符串,类试<?xml version=”1.0” encoding=”utf-8”?><message version="1.0"><header><messengerid>200911131015330000000001</messengerid><timestamp>20091113101533</timestamp></header><body><elements><element><lotteryid>112</lotteryid><issue>2009111301</issue></element></elements></body></message>这样的字符串.
我们可以用string或StringBuilder进行拼接进行发送,接收时再用XmlDocument进行读取,但这样,每出一个类型的xml的文档,我们都要进行这些相关的操作.后期维护及扩展的工作量都非常大.
于是,我做了如下设计及工作,希望大家学习及指点.一,我把这xml抽象为C#实体类,用属性表示元素(名相同),如元素下不是值,还是元素,再一层层的封装,中间的类实列名为元素名.即把上面的Xml文抽象为如下类结构(先不抽象<message>根目录).并为了演示简单,把所有数据类型都声明为string,
class ElementC
{ public string lotteryid
{get;set;}
public string issue
{get;set;}}
class ElementsC
{ pbulic ElementsC()
{element=new ElementC();}
public ElementC element
{get;set;}}
class BodyC
{public BodyC()
{elements=new ElementsC();}
public ElementsC elements
{get;set;}}
class HeaderC
{public string messengerid
{get;set;}
public string timestamp
{get;set;}}
class xmlDocumentC
{public xmlDocumentC()
{header=new HeaderC();
body=new BodyC();}
public HeaderC header
{get;set;}
public BodyC body
{get;set;}}
另外我用反射写了一个方法,把一个类的实列转换成XML字符串
public static string PropertyToXmlStringPart(object obj)
{//利用反射把类的属性名为XML元素,属性值为元素值,并转换成字符串,其属性支择list<>类型数据,用递归实现,其它类型没有实再.应加实现类,枚举,结构,数组等为属性的元素,有待加强. try
{ Type t = obj.GetType();
XmlDocument xmlDoc = new XmlDocument();
XmlElement root = xmlDoc.createElement_x_x_x_x("root");
foreach (PropertyInfo pi in t.GetProperties())
{ if (pi.PropertyType.IsGenericType)
{ object value1 = pi.GetValue(obj, null);
Type objType = pi.PropertyType;
int count = Convert.ToInt32(objType.GetProperty("Count").GetValue(value1, null));
for (int i = 0; i < count; i++)
{ XmlElement elem = xmlDoc.createElement_x_x_x_x(pi.Name);
object listItem = objType.GetProperty("Item").GetValue(value1, new object[] { i });
elem.InnerXml= PropertyToXmlStringPart(listItem root.A(elem); } }
else if (!pi.PropertyType.IsPrimitive && pi.PropertyType.IsClass && !pi.PropertyType.Name.Equals("String {
XmlElement elem = xmlDoc.createElement_x_x_x_x(pi.Name);
elem.InnerXml = PropertyToXmlStringPart(pi.GetValue(obj, null));
root.A(elem); }
else
{ XmlElement elem = xmlDoc.createElement_x_x_x_x(pi.Name);
try
{ elem.InnerText = pi.GetValue(obj, null).ToString();}
catch
{ elem.InnerText = string.Empty;}
root.A(elem);} }
xmlDoc.A(root);
XmlElement XmlEle = xmlDoc.DocumentElement;
return XmlEle.InnerXml; }
catch(Exception ex)
{ return ex.ToString();
} }
这个方法的输入参数为一个类实例,会根据据其属性值生成相应的XML字符串.
这样把每个类型的XML文档抽象成相应的类后,就可以自动生成XML字符串,方法中可以处理List<>的泛型,其它类型没有处理,但自定义类是没有问题的.
使用如下:xmlDocumentC xc=new xmlDocumentC();
xc.XXX=XXX;....xc付值,
string aa=PropertyToXmlStringPart(xc);这样就完成xml string.再转换为Xml Document就很简单了.
不知这个方法是不是很好,如那位朋友有更好的方法请多指教,
这是把类实列转换为xml string,但如何把xml document转换成类实列呢,以下是一种方法,我自己用反射写的,实现的List和系统定义类型,很笨..NET中有另一方法,我另用文单价绍
public void XmlNodeToObject(XmlNode xnode, object obj)
{
if (xnode.NodeType == XmlNodeType.Text)
{
bool isOk = true;
string fristParent = string.Empty;
fristParent = xnode.ParentNode.Name;
string secendParent = string.Empty;
string thirdParent = string.Empty;
try
{
secendParent = xnode.ParentNode.ParentNode.Name;
}
catch
{
isOk = false;
}
try
{
thirdParent = xnode.ParentNode.ParentNode.ParentNode.Name;
}
catch
{
isOk = false;
}
if (isOk)
{
Type t = obj.GetType();
foreach (PropertyInfo pi in t.GetProperties())
{
object oc = pi.GetValue(obj, null);
// string ccc=oc.GetType().Name;
// string bbbb=pi.PropertyType.Name;
if (oc != null)
{
if (pi.PropertyType.IsGenericType && pi.Name == secendParent)
{
foreach (Type tParam in pi.PropertyType.GetGenericArguments())
{
if (!tParam.IsGenericParameter)
{
Assembly asm = Assembly.GetExecutingAssembly();
int count = Convert.ToInt32(pi.PropertyType.GetProperty("Count").GetValue(pi.GetValue(obj, null), null));
if (count == 0)
{
object objc = asm.CreateInstance(tParam.Name, true);
tParam.GetProperty(fristParent).SetValue(objc, xnode.InnerText, null);
object[] occ = new object[1];
occ[0] = objc;
MethodInfo mi = pi.PropertyType.GetMethod("Add");//这只调用list的Add方法
mi.Invoke(oc, occ);
}
else
{
// bool AddNewOrUpdate = false;//list<T>中的一个T会有多个值,查T中的属性是否为空,为空就写值,否则,创建新的,
//查值
bool CreateNew = true;//确定要不要创建新的
for (int i = 0; i < count; i++)
{
//多项值
object listItem = pi.PropertyType.GetProperty("Item").GetValue(oc, new object[] { i });
if (listItem != null)
{
foreach (PropertyInfo pl in tParam.GetProperties())
{
if (pl.Name == fristParent)//查值是否为空
{
//查值
if (pl.GetValue(listItem, null)==null)
{
//更新值
tParam.GetProperty(fristParent).SetValue(listItem, xnode.InnerText, null);
CreateNew = false;
}
}
}
}
}
if (CreateNew)
{
//添加新的
object objc = asm.CreateInstance(tParam.Name, true);
tParam.GetProperty(fristParent).SetValue(objc, xnode.InnerText, null);
object[] occ = new object[1];
occ[0] = objc;
MethodInfo mi = pi.PropertyType.GetMethod("Add");//这只调用list的Add方法
mi.Invoke(oc, occ);
}
}
}
}
//
}
else if (!pi.PropertyType.IsPrimitive && pi.PropertyType.IsClass && !pi.PropertyType.Name.Equals("String") && pi.Name == secendParent)
{
PropertyInfo pii = oc.GetType().GetProperty(fristParent);
pii.SetValue(oc, xnode.InnerText, null);
}
else if (!pi.PropertyType.IsGenericType && !pi.PropertyType.IsPrimitive && pi.PropertyType.IsClass && !pi.PropertyType.Name.Equals("String"))
{
XmlNodeToObject(xnode, oc);
}
}
}
}
}
else
{
ForeachNodes(xnode, obj);
}
}
public void ForeachNodes(XmlNode node,object obj)
{
XmlNodeList children = node.ChildNodes;
foreach (XmlNode child in children)
{
if (child.NodeType == XmlNodeType.Text)
{
XmlNodeToObject(child, obj);
}
else if(child.NodeType == XmlNodeType.Element)
{
ForeachNodes(child, obj);
}
}
}