C#中將DataTable轉化成List<T>的方法解析
前言
通常在DAL層我們都需要把DataTable轉換為List<T>讓調(diào)用者盡可能的好用,盡量的不用關心數(shù)據(jù)庫的字段等,所以我們一般傳過去的都是List<T>而不是DataTable。
泛型的好處: 它為使用c#語言編寫面向對象程序增加了極大的效力和靈活性。不會強行對值類型進行裝箱和拆箱,或對引用類型進行。當涉及到兩者之間的轉換時,就顯得有些較為繁瑣。這個其中的問題主要在兩者的存儲方式,DataTable的存儲方式采用一種二維表的方式進行數(shù)據(jù)的存儲操作,DataTable表示內(nèi)存中數(shù)據(jù)的一個表。在List集合中,List的本質就是一個數(shù)組,則采用一種線性結構對數(shù)據(jù)進行存儲。
在轉換過程中,主要的問題在于不同類型的處理上,主要分為值類型和引用類型兩大類。
C#中值類型總是含有相應該類型的一個值,指類型包含:簡單類型(Simple types ),結構類型(struct types),枚舉類型(Enumeration types)。
- 簡單類型包含:整型,布爾型,字符型 (整型的一種特殊情況),浮點型,小數(shù)型。
- 整型包含:
sbyte、byte、short、ushort、int、uint、long、ulong和char。 - 引用類型:引用類型不存儲它們所代表的實際數(shù)據(jù),但它們存儲實際數(shù)據(jù)的引用。主要包含:對象類型,類類 型,接口,代表元,字符串類型,數(shù)組。
現(xiàn)提供轉換的代碼,僅供參考:
1.類型枚舉:
/// <summary>
/// 類型枚舉
/// </summary>
private enum ModelType
{
//值類型
Struct,
Enum,
//引用類型
String,
Object,
Else
}
private static ModelType GetModelType(Type modelType)
{
//值類型
if (modelType.IsEnum)
{
return ModelType.Enum;
}
//值類型
if (modelType.IsValueType)
{
return ModelType.Struct;
}
//引用類型 特殊類型處理
if (modelType == typeof(string))
{
return ModelType.String;
}
//引用類型 特殊類型處理
return modelType == typeof(object) ? ModelType.Object : ModelType.Else;
}
2.具體的轉換操作方法:
/// <summary>
/// datatable轉換為List<T>集合
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="table"></param>
/// <returns></returns>
public static List<T> DataTableToList<T>(DataTable table)
{
var list = new List<T>();
foreach (DataRow item in table.Rows)
{
list.Add(DataRowToModel<T>(item));
}
return list;
}
public static T DataRowToModel<T>(DataRow row)
{
T model;
var type = typeof(T);
var modelType = GetModelType(type);
switch (modelType)
{
//值類型
case ModelType.Struct:
{
model = default(T);
if (row[0] != null)
model = (T)row[0];
}
break;
//值類型
case ModelType.Enum:
{
model = default(T);
if (row[0] != null)
{
var fiType = row[0].GetType();
if (fiType == typeof(int))
{
model = (T)row[0];
}
else if (fiType == typeof(string))
{
model = (T)Enum.Parse(typeof(T), row[0].ToString());
}
}
}
break;
//引用類型 c#對string也當做值類型處理
case ModelType.String:
{
model = default(T);
if (row[0] != null)
model = (T)row[0];
}
break;
//引用類型 直接返回第一行第一列的值
case ModelType.Object:
{
model = default(T);
if (row[0] != null)
model = (T)row[0];
}
break;
//引用類型
case ModelType.Else:
{
//引用類型 必須對泛型實例化
model = Activator.CreateInstance<T>();
//獲取model中的屬性
var modelPropertyInfos = type.GetProperties();
//遍歷model每一個屬性并賦值DataRow對應的列
foreach (var pi in modelPropertyInfos)
{
//獲取屬性名稱
var name = pi.Name;
if (!row.Table.Columns.Contains(name) || row[name] == null) continue;
var piType = GetModelType(pi.PropertyType);
switch (piType)
{
case ModelType.Struct:
{
var value = Convert.ChangeType(row[name], pi.PropertyType);
pi.SetValue(model, value, null);
}
break;
case ModelType.Enum:
{
var fiType = row[0].GetType();
if (fiType == typeof(int))
{
pi.SetValue(model, row[name], null);
}
else if (fiType == typeof(string))
{
var value = (T)Enum.Parse(typeof(T), row[name].ToString());
if (value != null)
pi.SetValue(model, value, null);
}
}
break;
case ModelType.String:
{
var value = Convert.ChangeType(row[name], pi.PropertyType);
pi.SetValue(model, value, null);
}
break;
case ModelType.Object:
{
pi.SetValue(model, row[name], null);
}
break;
case ModelType.Else:
throw new Exception("不支持該類型轉換");
default:
throw new Exception("未知類型");
}
}
}
break;
default:
model = default(T);
break;
}
return model;
}
總結
以上的操作中,對不同類型有對應的處理方式。好了,以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流。

