前言
最近正在用 C# 寫一個小視窗軟體 , 裡面會有個功能就是讀取 XML 及寫入 XML , 但我懶 , 想說用 DataSet 來做就好了 , 但後面改了很多次 , 覺得 DataRow 的資料沒有型別 , 後面比較難維護 , 所以去 Google 搜尋看看如何做強型的 DataRow , 當然我找到了 , 不然不會寫這篇 , 這篇是個筆記 , 怕那個網址掛了以後沒得看了 , 原文網址在 : http://www.codeproject.com/KB/database/TypedDataTable.aspx?display=Print
本篇不是要翻譯原文 , 只是我自己整理的筆記自己看得懂就好了 , 有興趣的人直接看原文說明比較詳盡 , 這裡就用一個簡單的讀取及寫入 xml 檔案來做範例
範例說明
假設有一個 XML 檔案格式如下
<?xml version="1.0" encoding="utf-8" ?>
<tips>
<item><subject>Subject 1</subject><description>Some Text1 ...</description></item>
<item><subject>Subject 2</subject><description>Some Text2 ...</description></item>
</tips>
用 DataSet 其實就可以讀取這種格式並且更新內容後寫回 XML 檔案 , 但我們現在要用強型的 DataTable 做
範例程式
class MyRow : DataRow
{
/// <summary>
/// 讀取及設定標題
/// </summary>
public string subject
{
get { return (string)base["subject"]; }
set { base["subject"] = value; }
}
/// <summary>
/// 讀取及設定內容
/// </summary>
public string description
{
get { return (string)base["description"]; }
set { base["description"] = value; }
}
internal MyRow(DataRowBuilder builder)
: base(builder)
{
// 設定預設屬性
columnSubject = string.Empty;
columnDescription = string.Empty;
}
}
class MyTable : DataTable
{
public MyTable() : base("item")
{
Columns.Add(new DataColumn("subject", typeof(string)));
Columns.Add(new DataColumn("description", typeof(string)));
}
public void Add(MyRow row)
{
Rows.Add(row);
}
public void Remove(MyRow row)
{
Rows.Remove(row);
}
protected override Type GetRowType()
{
return typeof(MyRow);
}
protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
{
return new MyRow(builder);
}
// public new MyRow NewRow()
// {
// MyRow row = (MyRow)NewRow();
// return row;
// }
public MyRow GetNewRow()
{
MyRow row = (MyRow)NewRow();
return row;
}
/// <summary>
/// 寫這個可以用陣列方式取得所有的 MyRow
/// </summary>
/// <param name="idx"></param>
/// <returns></returns>
public MyRow this[int idx]
{
get { return (MyRow)Rows[idx]; }
}
}
MyTable 及 MyRow 這兩個類別分別繼承自 DataTable 及 DataRow , 現在就可以用下面的方式新增一筆 XML 資料
DataSet ds = new DataSet();
MyTable table = new MyTable();
ds.ReadXml("test.xml");
ds.Tables.Add(table);
MyRow row = table.GetNewRow();
row.subject= "subject 3";
row.description = "description 3";
table.Add(row);
ds.WriteXml("test.xml");
稍微講解一下
基本上有一些 method 必須複寫(override) , 行 49 , 54 是必須的 , 這樣才有辦法用 MyTable 去產生 MyRow 的型別 , 而行 33 的 base("item") 是為了 XML 範例做的 , 因為每一行資料都是 <item> , 在 DataTable 的 name 就要指定成 "item" , 所以用 base("item") 呼叫 DataTable 的建構子做
行 21 也是必須的 , 我不明白其道理 , 看 MSDN 只知道這個建構子必須要有 , 我想應該和 MyTable.NewRowFromBuilder() 有關係
而在 MyRow 中我定義了 MyRow.subject 及 MyRow.description 分別對應到 XML 的 <subject> 及 <description> 的欄位 , 在 VS.NET 編輯器中就可以自動跳出類別的屬性使用 , 而且編譯時期也會檢查型別
寫的很簡單 , 我覺得應該看原文會比較清楚整個來龍去脈 , 而且原文也有介紹怎麼定義事件 , 講解完B ...