// dt:数据源 isconvert: false时需要确保datatable列类型与实体对应以免除类型转换,速度更快 true:会进行类型转换
static List<T> ByExpTree<T>(DataTable dt, bool isconvert = false)
{
var props = typeof(T).GetProperties().Where(p => dt.Columns.Contains(p.Name)).Select(x => new { a = x });
var param = Expression.Parameter(typeof(DataRow), "dr");
List<Expression> exps = new List<Expression>();
var cre = Expression.New(typeof(T));
var newb = Expression.Variable(typeof(T));
var assb = Expression.Assign(newb, cre);
exps.Add(assb);
MethodInfo field = typeof(DataRowExtensions).GetMethod("Field", new Type[] { typeof(DataRow), typeof(string) });
// 使用时注意将Program改为 ChangeType所在类
var mtd = isconvert ? typeof(Program).GetMethod("ChangeType", new Type[] { typeof(object) }) : null;
foreach (var item in props)
{
var setexp = Expression.MakeMemberAccess(newb, item.a);
BinaryExpression ass;
if (isconvert)
{
MethodInfo fieldext = field.MakeGenericMethod(typeof(object));
MethodCallExpression mceExpr = Expression.Call(fieldext, param, Expression.Constant(item.a.Name));
var mtdext = mtd.MakeGenericMethod(item.a.PropertyType);
var cvt = Expression.Call(mtdext, mceExpr);
ass = Expression.Assign(setexp, cvt);
}
else
{
MethodInfo fieldext = field.MakeGenericMethod(item.a.PropertyType);
MethodCallExpression mceExpr = Expression.Call(fieldext, param, Expression.Constant(item.a.Name));
ass = Expression.Assign(setexp, mceExpr);
}
exps.Add(ass);
}
exps.Add(newb);
var body = Expression.Block(new ParameterExpression[] { newb }, exps);
var sel = Expression.Lambda<Func<DataRow, T>>(body, param);
var dt2 = dt.AsEnumerable();
return dt2.Select(sel.Compile()).ToList();
}
// 类型转换
public static T ChangeType<T>(object value)
{
var t = typeof(T);
if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
{
if (value == null)
{
return default(T);
}
t = Nullable.GetUnderlyingType(t);
}
return (T)Convert.ChangeType(value, t);
}
PS: 部分代码来源于网络,调整改造成datatable转实体,此方式转换比反射速度快很,如果不作类型转换会更快, 仅作备忘记录;