/// <summary> /// 将ExcelDataRow快速转换为指定类型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="dataRow"></param> /// <returns></returns> public static T FastConvert <T>(ExcelDataRow dataRow) { //利用表达式树,动态生成委托并缓存,得到接近于硬编码的性能 //最终生成的代码近似于(假设T为Person类) //Func<ExcelDataRow,Person> // new Person(){ // Name = Convert(ChangeType(dataRow.DataCols.SingleOrDefault(c=>c.PropertyName == prop.Name).ColValue,prop.PropertyType),prop.ProertyType), // Age = Convert(ChangeType(dataRow.DataCols.SingleOrDefault(c=>c.PropertyName == prop.Name).ColValue,prop.PropertyType),prop.ProertyType) // } // } string propertyNames = string.Empty; dataRow.DataCols.ForEach(c => propertyNames += c.PropertyName + "_"); var key = typeof(T).FullName + "_" + propertyNames.Trim('_'); if (!Table.ContainsKey(key)) { List <MemberBinding> memberBindingList = new List <MemberBinding>(); MethodInfo singleOrDefaultMethod = typeof(Enumerable) .GetMethods() .Single(m => m.Name == "SingleOrDefault" && m.GetParameters().Count() == 2) .MakeGenericMethod(new[] { typeof(ExcelDataCol) }); foreach (var prop in typeof(T).GetProperties()) { Expression <Func <ExcelDataCol, bool> > lambdaExpr = c => c.PropertyName == prop.Name; MethodInfo changeTypeMethod = typeof(ExpressionMapper).GetMethods().Where(m => m.Name == "ChangeType").First(); Expression expr = Expression.Convert( Expression.Call(changeTypeMethod , Expression.Property( Expression.Call( singleOrDefaultMethod , Expression.Constant(dataRow.DataCols) , lambdaExpr) , typeof(ExcelDataCol), "ColValue"), Expression.Constant(prop.PropertyType)) , prop.PropertyType); memberBindingList.Add(Expression.Bind(prop, expr)); } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(T)), memberBindingList.ToArray()); Expression <Func <ExcelDataRow, T> > lambda = Expression.Lambda <Func <ExcelDataRow, T> >(memberInitExpression, new ParameterExpression[] { Expression.Parameter(typeof(ExcelDataRow), "p") }); Func <ExcelDataRow, T> func = lambda.Compile();//拼装是一次性的 Table[key] = func; } var ss = (Func <ExcelDataRow, T>)Table[key]; return(((Func <ExcelDataRow, T>)Table[key]).Invoke(dataRow)); }
/// <summary> /// 设置Excel行的校验结果 /// </summary> /// <param name="row"></param> /// <param name="isValid"></param> /// <param name="col"></param> /// <param name="errorMsg"></param> public static void SetNotValid(this ExcelDataRow row, bool isValid, ExcelDataCol dataCol, string errorMsg) { if (!isValid) { row.IsValid = false; row.ErrorMsg += dataCol.ColName + errorMsg + ";"; } }
/// 直接反射 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="row"></param> /// <returns></returns> //public static T Convert<T>(this ExcelDataRow row) //{ // return Convert<T>(row, GetValue); //} /// <summary> /// 将ExcelDataRow转换为指定类型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="row"></param> /// <returns></returns> private static T Convert <T>(this ExcelDataRow row, Func <ExcelDataRow, Type, string, object> func) { Type t = typeof(T); object o = Activator.CreateInstance(t); t.GetProperties().ToList().ForEach(p => { if (p.IsDefined(typeof(ColNameAttribute))) { p.SetValue(o, func(row, p.PropertyType, p.GetCustomAttribute <ColNameAttribute>().ColName)); } }); return((T)o); }
/// <summary> /// 利用反射将ExcelDataRow转换为制定类型,性能较差 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="row"></param> /// <returns></returns> //public static T ConvertByRefelection<T>(this ExcelDataRow row) //{ // Type t = typeof(T); // object o = Activator.CreateInstance(t); // t.GetProperties().ToList().ForEach(p => { // if (p.IsDefined(typeof(ColNameAttribute))) // { // ExcelDataCol col = row.DataCols.SingleOrDefault(c => c.ColName == p.GetCustomAttribute<ColNameAttribute>().ColName); // if (col != null) // { // p.SetValue(o, ExpressionMapper.ChangeType(col.ColValue, p.PropertyType)); // } // } // }); // return (T)o; //} /// <summary> /// 利用表达式树,将ExcelDataRow快速转换为指定类型 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="row"></param> /// <returns></returns> public static T FastConvert <T>(this ExcelDataRow row) { return(ExpressionMapper.FastConvert <T>(row)); }