這篇討論使用建構式內部實作的方式來完成字串陣列解析為強型別物件。
內部實作法大致可分為幾個方式:
- 多載建構子,然後直接在建構式內呼叫內部的解析對應程式碼將字串陣列的值對應到屬性上。
- 使用抽象,可以使用抽象類別 (abstract Class) 或是介面 (Interface) 建立一個解析的功能抽象,然後由資料類別實作。
這個系列文會用到兩個基本的 CSV 形式的文字檔,分別列出如下:
TextFile1.txt:
1,ABC,甲
2,DEF,乙
3,GHI,丙
TextFile2.txt:
1,你,Sunday,看戲
2,我,Monday,看電影
3,他,Tuesday,爬山
4,她,Wednesday,見鬼了
分別對應以下的資料型別:(為了對照方便,先把漂亮的命名這檔事丟一邊)
public class DataForTextFile1
{
public int Index { get; set; }
public string English { get; set; }
public string Chinese { get; set; }
}
public class DataForTextFile2
{
public int Index { get; set; }
public string Person { get; set; }
public DayOfWeek WeekDay { get; set; }
public string Activity { get; set; }
}
至於讀取文字檔的方式,因為不是要介紹的重點,因此採用最簡單的寫法 -- File.ReadAllLines 方法,避免在這邊夾纏不清、模糊焦點。
第一個先來實作建構子多載的方式,修改兩個資料型別內容:
public class DataForTextFile1
{
public DataForTextFile1() : this(null)
{ }
public DataForTextFile1(string[] items)
{
if (items == null)
{ return; }
if (items != null && items.Count() < 3)
{ throw new ArgumentException(); }
Index = int.Parse(items[0]);
English = items[1];
Chinese = items[2];
}
public int Index { get; set; }
public string English { get; set; }
public string Chinese { get; set; }
}
public class DataForTextFile2
{
public DataForTextFile2() : this(null)
{ }
public DataForTextFile2(string[] items)
{
if (items == null)
{ return; }
if (items != null && items.Count() < 4)
{ throw new ArgumentException(); }
Index = int.Parse(items[0]);
Person = items[1];
WeekDay =(DayOfWeek )Enum.Parse(typeof(DayOfWeek), items[2]);
Activity = items[3];
}
public int Index { get; set; }
public string Person { get; set; }
public DayOfWeek WeekDay { get; set; }
public string Activity { get; set; }
}
然後寫個程式來看結果 (當然如果你會寫測試的話,能夠寫測試程式碼是最好的了,但為了普羅大眾容易 Copy & Paste,我決定還是寫個 Console 程式作為展示之用。):
class Program
{
static void Main(string[] args)
{
ProcessTextFile1();
Console.WriteLine();
Console.WriteLine("**********************************");
Console.WriteLine();
ProcessTextFile2();
Console.ReadLine();
}
static void ProcessTextFile1()
{
var lines= File.ReadAllLines("TextFile1.txt");
List<DataForTextFile1> list= new List<DataForTextFile1>();
foreach (var line in lines)
{
string[] items = line.Split(',');
if (items != null)
{
list.Add(new DataForTextFile1(items));
}
}
// 顯示結果
foreach (var item in list)
{
Console.WriteLine(item.Index.ToString());
Console.WriteLine(item.English);
Console.WriteLine(item.Chinese);
Console.WriteLine("---------------------");
}
}
static void ProcessTextFile2()
{
var lines = File.ReadAllLines("TextFile2.txt");
List<DataForTextFile2> list = new List<DataForTextFile2>();
foreach (var line in lines)
{
string[] items = line.Split(',');
if (items != null)
{
list.Add(new DataForTextFile2(items));
}
}
// 顯示結果
foreach (var item in list)
{
Console.WriteLine(item.Index.ToString());
Console.WriteLine(item.Person );
Console.WriteLine(item.WeekDay );
Console.WriteLine(item.Activity);
Console.WriteLine("---------------------");
}
}
}
有些人可能會有疑問,為什麼我不乾脆傳一整行甚至整篇文字內容進去然後在資料型別內部執行 String.Split,而要傳一個字串陣列,這原因是 (1) 來源文字檔的分隔符號未必是逗點 (2) 來源文字檔也未必是使用分隔符號,有一種常見的文字檔格式是固定字串長度分隔 (3) 搞不好你的字串陣列是拼湊好幾個檔案來的;基於以上幾個理由,我把建立字串陣列的實作移到客戶端。