1,准备如下的XML文件
2,新建与XML文件中节点名相同的数据类,用来保存配置文件中各个节点的设定值。按照上面XML文件结构,创建以下类:
注意每个类的命名,它们和XML文件中每个节点的名字必须完全相同,否则在使用反射不能对类对象进行数据设定,另外每个类中的属性名也要与文件中节点的属性一致,对于文件中存在子节点的节点,类的创建方法可参照Test3类的编写方法,用范型List<>来保存并列的子节点。
3,节点的读取,参照下面代码中的ReadConfigInfo()和initNodeObject()方法
代码讨论:
1,在上记代码中统一使用了类属性,即每个属性带有get和set方法,当然也可以使用类字段。
2,在ReadConfigInfo()和initNodeObject()方法中都用到反射。
在ReadConfigInfo()中使用如下语句取得需要保存Xml文件节点配置信息的类对象,
Type selfType = this.GetType();
PropertyInfo[] proLst = selfType.GetProperties(); //如果使用类字段, 应该使用GetFileds()方法,取得FieldInfo类型数组,
以下语句是用来实例化对象的,这里看不到new操作符了哦
Type proType = pro.PropertyType;
string typeName = proType.FullName;
//创建节点对象
object nodeObj = Activator.CreateInstance(proType);
//把结果保存到相应的属性中。
pro.SetValue(this, nodeObj, null);
在initNodeObject()方法中,应用方法与上记说明基本相同,不同的是这是一个第归方法,用于取得含有子节点Xml节点中的数据。对于含有子节点的Xml节点,使用以下语句判断对应的类对象中保存字节点的属性
if (pro.PropertyType.IsGenericType == false)
{
//当前节点属性值设定
}
else
{
//取得保存子节点数据的对象类型
Type t = pro.PropertyType;
//创建对象实例
Object olist = Activator.CreateInstance(t);
//取得范型对象可以保存的数据类型
Type[] typeParam = t.GetGenericArguments();
//取得向List中添加数据的方法
MethodInfo addMethod = t.GetMethod("Add");
//其他处理可参照代码中的注释。
}
综上所述,读取XML文件配置数据的方法就写完了,以后,如果要在XML文件中追加配置信息,只需要在工程中添加对应的节点类,在TestConfig类中追加对应的类的属性就可以了。ReadConfigInfo()和initNodeObject()方法就会完成对应设定处理。
- <TestConfig>
- <Test1 Name="aaa" Code="001" />
- <Test2 Name="bbb" Code="002" DefaultText="Wellcome" />
- <Test3 Name="ccc" Code="003" >
- <Item Name="item1" Value="item1" />
- <Item Name="item2" Value="item2" />
- </Test3>
- </TestConfig>
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflection.config
- {
- //Test1节点对应的Class
- public class Test1
- {
- //构造器
- public Test1()
- {
- //
- }
- //节点属性-Name
- private string name;
- public string Name
- {
- set { this.name = value; }
- get { return this.name; }
- }
- //节点属性-Code
- private string code;
- public string Code
- {
- set { this.code = value; }
- get { return this.code; }
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflection.config
- {
- //Test2节点对应的Class
- public class Test2
- {
- //构造器
- public Test2()
- {
- //
- }
- //节点属性-Name
- private string name;
- public string Name
- {
- set { this.name = value; }
- get { return this.name; }
- }
- //节点属性-Code
- private string code;
- public string Code
- {
- set { this.code = value; }
- get { return this.code; }
- }
- //节点属性-DefaultText;
- private string defaultText;
- public string DefaultText
- {
- set { this.defaultText = value; }
- get { return this.defaultText; }
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflection.config
- {
- //节点Test3对应的Class
- public class Test3
- {
- //构造器
- public Test3()
- {
- //
- }
- //节点属性-Name
- private string name;
- public string Name
- {
- set { this.name = value; }
- get { return this.name; }
- }
- //节点属性-Code
- private string code;
- public string Code
- {
- set { this.code = value; }
- get { return this.code; }
- }
- //子节点的List-Item
- private List<Item> itemLst;
- public List<Item> ItemLst
- {
- set { this.itemLst = value; }
- get { return this.itemLst; }
- }
- }
- }
- using System;
- using System.Collections.Generic;
- using System.Text;
- namespace reflection.config
- {
- //节点Item对应的Class
- public class Item
- {
- //构造器
- public Item()
- {
- //
- }
- //节点属性-Name
- private string name;
- public string Name
- {
- set { this.name = value; }
- get { return this.name; }
- }
- //节点属性-Value
- private string value;
- public string Value
- {
- set { this.value = value; }
- get { return this.value; }
- }
- }
- }
3,节点的读取,参照下面代码中的ReadConfigInfo()和initNodeObject()方法
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Xml;
- using System.Reflection;
- namespace reflection.config
- {
- //读取Xml文件中的配置信息时的Class
- public class TestConfig
- {
- //xml文件的路径
- private string filePath;
- //构造器
- public TestConfig(string configFilePath)
- {
- //
- filePath = configFilePath;
- }
- //节点属性-Test1
- private Test1 test1;
- public Test1 TestOne
- {
- set { this.test1 = value; }
- get { return this.test1; }
- }
- //节点属性-test2
- private Test2 test2;
- public Test2 TestTwo
- {
- set { this.test2 = value; }
- get { return this.test2; }
- }
- //节点属性-test3
- private Test3 test3;
- public Test3 TestThree
- {
- set { this.test3 = value; }
- get { return this.test3; }
- }
- /// <summary>
- /// 读取XML文件中各节点信息
- /// </summary>
- public void ReadConfigInfo()
- {
- try
- {
- XmlDocument xmlDoc = new XmlDocument();
- xmlDoc.Load(filePath);
- Type selfType = this.GetType();
- PropertyInfo[] proLst = selfType.GetProperties();
- foreach (PropertyInfo pro in proLst)
- {
- Type proType = pro.PropertyType;
- string typeName = proType.FullName;
- //创建节点对象
- object nodeObj = Activator.CreateInstance(proType);
- initNodeObject(xmlDoc, nodeObj, 0);
- pro.SetValue(this, nodeObj, null);
- }
- //读取节点Test1的数据
- /*Test1 t1 = new Test1();
- initNodeObject(xmlDoc, t1, 0);
- this.TestOne = t1;
- //读取节点Test2的数据
- Test2 t2 = new Test2();
- initNodeObject(xmlDoc, t2, 0);
- this.TestTwo = t2;
- //读取节点Test3的数据
- Test3 t3 = new Test3();
- initNodeObject(xmlDoc, t3, 0);
- this.TestThree = t3;*/
- }
- catch (Exception ex)
- {
- throw new Exception("从testConfig.xml文件中读取配置信息时,发生错误!" , ex.InnerException);
- }
- }
- /// <summary>
- /// 把XML文件中节点信息读取到指定的对象中
- /// </summary>
- /// <param name="xmlDoc">XML文件的DOC对象</param>
- /// <param name="nodeObj">保存节点信息的对象</param>
- private void initNodeObject(XmlDocument xmlDoc, Object nodeObj, int nodeIndex)
- {
- string nodeName = nodeObj.GetType().Name;
- //取得XML文件中对应的节点
- XmlNode node = xmlDoc.GetElementsByTagName(nodeName).Item(nodeIndex);
- //取得对象的属性列表
- PropertyInfo[] proLst = nodeObj.GetType().GetProperties();
- foreach (PropertyInfo pro in proLst)
- {
- if (pro.PropertyType.IsGenericType == false)
- {
- string fieldName = pro.Name;
- //取得配置文件中的设定值
- string configValue = node.Attributes.GetNamedItem(fieldName).Value;
- //把取得数据保存到对象的属性中
- pro.SetValue(nodeObj, configValue, null);
- }
- else
- {
- Type t = pro.PropertyType;
- Object olist = Activator.CreateInstance(t);
- Type[] typeParam = t.GetGenericArguments();
- MethodInfo addMethod = t.GetMethod("Add");
- if (typeParam.Length == 1)
- {
- Type paramType = typeParam[0];
- //取得节点名称
- string childNodeName = paramType.Name;
- //取得节点列表
- XmlNodeList nodeLst = xmlDoc.GetElementsByTagName(childNodeName);
- int count = 0;
- foreach (XmlElement element in nodeLst)
- {
- //创建一个参数类型的实例
- object obj = Activator.CreateInstance(paramType);
- initNodeObject(xmlDoc, obj, count);
- count = count + 1;
- addMethod.Invoke(olist, new object[] { obj });
- }
- pro.SetValue(nodeObj, olist, null);
- }
- }
- }
- }
- }
- }
1,在上记代码中统一使用了类属性,即每个属性带有get和set方法,当然也可以使用类字段。
2,在ReadConfigInfo()和initNodeObject()方法中都用到反射。
在ReadConfigInfo()中使用如下语句取得需要保存Xml文件节点配置信息的类对象,
Type selfType = this.GetType();
PropertyInfo[] proLst = selfType.GetProperties(); //如果使用类字段, 应该使用GetFileds()方法,取得FieldInfo类型数组,
以下语句是用来实例化对象的,这里看不到new操作符了哦
Type proType = pro.PropertyType;
string typeName = proType.FullName;
//创建节点对象
object nodeObj = Activator.CreateInstance(proType);
//把结果保存到相应的属性中。
pro.SetValue(this, nodeObj, null);
在initNodeObject()方法中,应用方法与上记说明基本相同,不同的是这是一个第归方法,用于取得含有子节点Xml节点中的数据。对于含有子节点的Xml节点,使用以下语句判断对应的类对象中保存字节点的属性
if (pro.PropertyType.IsGenericType == false)
{
//当前节点属性值设定
}
else
{
//取得保存子节点数据的对象类型
Type t = pro.PropertyType;
//创建对象实例
Object olist = Activator.CreateInstance(t);
//取得范型对象可以保存的数据类型
Type[] typeParam = t.GetGenericArguments();
//取得向List中添加数据的方法
MethodInfo addMethod = t.GetMethod("Add");
//其他处理可参照代码中的注释。
}
综上所述,读取XML文件配置数据的方法就写完了,以后,如果要在XML文件中追加配置信息,只需要在工程中添加对应的节点类,在TestConfig类中追加对应的类的属性就可以了。ReadConfigInfo()和initNodeObject()方法就会完成对应设定处理。