前回在C#反射實踐的文章中,只介紹了利用反射如何把Xml檔案中的資料讀取設定到類對象的屬性中的方法,這回來介紹如何利用反射機制把值對象寫入Xml檔案的方法
本文介紹的把值對象寫入Xml檔案的方法,有以下幾點約束
1、值對象中的所有屬性必須是string類型的,不含儲存子節點資訊的屬性;
2、自節點資料是儲存在範型List中的值對象。
下面的saveToFile()方法是詳細的代碼實現,
首先需要在類檔案中引入以下.Net的命名空間:
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Xml;
- using System.Reflection;
- using System.IO;
代碼實現:saveToFile()方法,
- /// <summary>
- /// 把指定的值對象的屬性值儲存到Xml檔案中相應的節點中,並儲存到檔案中
- /// </summary>
- /// <param name="obj">需要儲存的值對象</param>
- /// <param name="parentNode">儲存值對象資料的父節點</param>`
- /// <param name="nodeIndex">子節點的索引</param>
- /// <history>
- private void saveToFile(object obj, XmlNode parentNode, int nodeIndex)
- {
- //取得類名稱,作為xml檔案的節點名。
- string nodeName = obj.GetType().Name;
- //取得指定對象的屬性
- PropertyInfo[] proLst = obj.GetType().GetProperties();
- //準備儲存值對象屬性值得xml的節點對象。
- XmlNode node = null;
- //取得節點的個數
- int nodeCount = xmlDoc.GetElementsByTagName(nodeName).Count;
- //節點存時,取得已經存在的節點
- if (nodeIndex < nodeCount)
- {
- node = xmlDoc.GetElementsByTagName(nodeName).Item(nodeIndex);
- }
- //節點不存在時,建立一個新的節點,並把這個節點追加到xml的文檔對象中
- if (node == null)
- {
- node = xmlDoc.CreateElement(nodeName);
- if (parentNode == null)
- {
- this.rootNode.AppendChild(node);
- }
- else
- {
- parentNode.AppendChild(node);
- }
- }
- //把對象的屬性值儲存到Xml文檔對象的對應的節點屬性中
- foreach (PropertyInfo pro in proLst)
- {
- XmlElement xmlE = (XmlElement)node;
- //屬性是值對象的場合,只認string資料類型哦
- if (pro.PropertyType.Name.IndexOf("String") >= 0)
- {
- //設定xml節點的屬性值
- xmlE.SetAttribute(pro.Name, pro.GetValue(obj, null).ToString());
- }
- //屬性是範型的場合,此預設資料類型是範型List<>
- else if (pro.PropertyType.IsGenericType == true)
- {
- //利用反射取得屬性的get方法。
- MethodInfo m = pro.GetGetMethod();
- //利用反射調用屬性的get方法,取得屬性的值
- object rs = m.Invoke(obj, null);
- //取得List中的對象數
- int count = (int)rs.GetType().GetProperty("Count").GetValue(rs, null);
- for (int i = 0; i < count; i++)
- {
- //取得List中指定索引的對象
- object param = rs.GetType().GetProperty("Item").GetValue(rs, new object[] { i });
- //第歸調用實現子節點的向Xml的文檔對象的儲存
- saveToFile(param, node, i);
- }
- }
- //Xml節點對象的場合
- else
- {
- //利用反射取得屬性的get方法。
- MethodInfo m = pro.GetGetMethod();
- //利用反射調用屬性的get方法,取得屬性的值
- object rs = m.Invoke(obj, null);
- saveToFile(rs, node, 0);
- }
- }
- //把xml的文檔對象儲存到指定的xml檔案中
- xmlDoc.Save(this.filePath);
- }
注意:在上面的代碼要想正常編譯,需要聲明一下類的欄位變數
- //xml檔案的路徑
- private string filePath;
- //儲存xml檔案資訊的文檔對象
- private XmlDocument xmlDoc = null;
- //xml檔案的根節點名
- private string rootNodeName = "ReflectionTest";
- //xml檔案的根節點對象
- private XmlNode rootNode;
類的構造器請參照下記代碼:
- //構造器
- public TestConfig(string configFilePath)
- {
- xmlDoc = new XmlDocument();
- createXmlRootNode(filePath);
- filePath = configFilePath;
- }
上面的createXmlRootNode方法,是用來初始化Xml的文檔對象-XmlDocument的,實現方式如下:
- /// <summary>
- /// 初始化XMLDocument對象
- /// </summary>
- /// <param name="fileName">Xml的檔案名稱</param>
- private void createXmlRootNode(string fileName)
- {
- if (File.Exists(fileName) == true)
- {
- xmlDoc.Load(fileName);
- rootNode = xmlDoc.GetElementsByTagName(rootNodeName).Item(0);
- }
- else
- {
- xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "UTF-8", null));
- rootNode = xmlDoc.CreateElement(rootNodeName);
- xmlDoc.AppendChild(rootNode);
- }
- }
saveToFile()方法的調用方法如下:
- /// <summary>
- /// 把指定的值對象的屬性值儲存到Xml檔案中
- /// </summary>
- public void saveToXml()
- {
- saveToFile(this, null, 0);
- }
上面代碼中的this可以是任意的一個按照本文約束規則編寫的值對象,null表示要把這值對象作為Xml檔案的根節點進行設定,0這個參數是針對一個值對象中包含有範型List<>類型的字對象的情況,如果沒有這種類型,直接設定成0就可以了,如果有請參照saveToFile()方法中第歸調用時的設定方法,它的值就是List中對象的索引值。