在.net項目中使用到DataTable和List<T>集合的地方較多, 泛型的好處: 它為使用c#語言編寫面向對象程序增加了極大的效力和靈活性。不會強行對值類型進行裝箱和拆箱,或對引用類型進行。當涉及到兩者之間的轉換時,就顯得有些較為繁瑣。這個其中的問題主要在兩者的存儲方式,DataTable的存儲方式采用一種二維表的方式進行數據的存儲操作,DataTable表示內存中數據的一個表。在List集合中,List的本質就是一個數組,則采用一種線性結構對數據進行存儲。
在轉換過程中,主要的問題在於不同類型的處理上,主要分為值類型和引用類型兩大類。
C#中值類型總是含有相應該類型的一個值,指類型包含:簡單類型(Simple types ),結構類型(struct types),枚舉類型(Enumeration types)。
簡單類型包含:整型,布爾型,字符型 (整型的一種特殊情況),浮點型,小數型。
整型包含: sbyte 、byte、 short、 ushort、 int、 uint、 long、 ulong 和 char。
引用類型:引用類型不存儲它們所代表的實際數據,但它們存儲實際數據的引用。主要包含:對象類型,類類 型,接口,代表元,字符串類型,數組。
現提供轉換的代碼,僅供參考:
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;
}
以上的操作中,對不同類型有對應的處理方式。