[C#]利用 Using 縮排程式碼
常遇到要將資料輸出成 XML 格式的需求,使用 .Net 內建的 XmlWriter 寫出來的程式碼太平不易讀,倘若要求的 XML 格式稍微複雜一點,轉檔的程式也就跟著變的更難以閱讀。
也曾試過自己手動加上縮排,但常一不注意就被 IDE 很貼心的自動重排了,以下就利用 using 、Extension 等技巧來克服此問題。
很平滑的程式碼
{
w.WriteStartElement("Request");
w.WriteStartElement("Access");
w.WriteStartElement("Authentication");
w.WriteEndElement();
w.WriteStartElement("Connection");
w.WriteEndElement();
w.WriteStartElement("Organization");
w.WriteEndElement();
w.WriteStartElement("Locale");
w.WriteEndElement();
w.WriteEndElement();
w.WriteStartElement("RequestContent");
w.WriteEndElement();
w.WriteEndElement();
}
改善後的程式碼
{
using (w.Element("Request"))
{
using (w.Element("Access"))
{
using (w.Element("Authentication")) { }
using (w.Element("Connection")) { }
using (w.Element("Organization")) { }
using (w.Element("Locale")) { }
}
using (w.Element("RequestContent"))
{
}
}
}
縮排後的程式碼看起來就跟輸出的 XML 結構相仿。
測試程式及測試資料
{
var ds = CreateTestDataSet();
var data = ConvertToXmlFormat(ds, "Master");
Console.WriteLine(data);
Console.ReadLine();
}
private static DataSet CreateTestDataSet()
{
var master = new DataTable { TableName = "Master" };
AddColumns(master, "key", "number", "time");
master.Rows.Add("10","2048","2013-12-31 23:59:59");
var detailA = new DataTable { TableName = "DetailA"};
AddColumns(detailA, "key", "item", "qty");
detailA.Rows.Add("10", "Coke", 10);
detailA.Rows.Add("10", "Cookie", 100);
var detailB = new DataTable { TableName = "DetailB"};
AddColumns(detailB, "key", "note");
detailB.Rows.Add("10", "test1...");
detailB.Rows.Add("10", "test2...");
detailB.Rows.Add("10", "test3...");
var ds = new DataSet();
ds.Tables.AddRange(new[] { master, detailA, detailB });
return ds;
}
private static void AddColumns(DataTable t, params string[] colNames)
{
foreach (var col in colNames)
t.Columns.Add(col);
}
執行的結果
<Request>
<Access>
<Authentication user="user" password="password" />
<Connection application="" source="" />
<Organization name="GAME" />
<Locale language="zh-tw" />
</Access>
<RequestContent>
<Document>
<RecordSet id="1">
<Master name="Master">
<Record>
<Field name="key" value="10" />
<Field name="number" value="2048" />
<Field name="time" value="2013-12-31 23:59:59" />
</Record>
</Master>
<Detail name="DetailA">
<Record>
<Field name="key" value="10" />
<Field name="item" value="Coke" />
<Field name="qty" value="10" />
</Record>
<Record>
<Field name="key" value="10" />
<Field name="item" value="Cookie" />
<Field name="qty" value="100" />
</Record>
</Detail>
<Detail name="DetailB">
<Record>
<Field name="key" value="10" />
<Field name="note" value="test1..." />
</Record>
<Record>
<Field name="key" value="10" />
<Field name="note" value="test2..." />
</Record>
<Record>
<Field name="key" value="10" />
<Field name="note" value="test3..." />
</Record>
</Detail>
</RecordSet>
</Document>
</RequestContent>
</Request>
核心程式 (要改善的目標物)
{
using (var mem = new MemoryStream())
{
var settings = new XmlWriterSettings();
settings.Indent = true;
using (var w = XmlWriter.Create(mem, settings))
{
using (w.Element("Request"))
{
WriteAccessNode(w);
AddContentNode(w, dataSet, masterTableName);
}
}
return Encoding.UTF8.GetString(mem.ToArray());
}
}
private static void WriteAccessNode(XmlWriter w)
{
using (w.Element("Access"))
{
using (w.Element("Authentication"))
{
w.Attribute("user", "user");
w.Attribute("password", "password");
}
using (w.Element("Connection"))
{
w.Attribute("application", "");
w.Attribute("source", "");
}
using (w.Element("Organization"))
{
w.Attribute("name", "GAME");
}
using (w.Element("Locale"))
{
w.Attribute("language", "zh-tw");
}
}
}
private static void AddContentNode(XmlWriter w, DataSet dataSet, string masterTableName)
{
using (w.Element("RequestContent"))
{
using (w.Element("Document"))
{
using (w.Element("RecordSet"))
{
w.Attribute("id", "1");
using (w.Element("Master"))
{
w.Attribute("name", masterTableName);
WriteTable(w, dataSet.Tables[masterTableName]);
}
foreach (DataTable table in dataSet.Tables)
{
if (table.TableName == masterTableName) continue;
using (w.Element("Detail"))
{
w.Attribute("name", table.TableName);
WriteTable(w, table);
}
}
}
}
}
}
private static void WriteTable(XmlWriter w, DataTable table)
{
foreach (DataRow row in table.Rows)
{
using (w.Element("Record"))
{
foreach (DataColumn col in table.Columns)
{
using (w.Element("Field"))
{
w.Attribute("name", col.ColumnName);
w.Attribute("value", row[col].ToString());
}
}
}
}
}
相關的 Extension 及 class
{
public static XNode Element(this XmlWriter w, string name)
{
return new XNode(name, w);
}
public static void Attribute(this XmlWriter w, string name, string value)
{
w.WriteAttributeString(name, value);
}
}
public class XNode : IDisposable
{
private readonly XmlWriter _w;
public XNode(string name, XmlWriter w)
{
_w = w;
_w.WriteStartElement(name);
}
public void Dispose()
{
_w.WriteEndElement();
}
}