/// <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]; var t = ((Func <ExcelDataRow, T>)Table[key]).Invoke(dataRow); return(t); }
/// <summary> /// 设置Excel行的校验结果 /// </summary> /// <param name="row"></param> /// <param name="isValid"></param> /// <param name="col"></param> /// <param name="errorMsg"></param> public static void SetState(this ExcelDataRow row, bool isValid, ExcelDataCol dataCol, string errorMsg) { if (!isValid) { row.IsValid = isValid; row.ErrorMsg = dataCol.ColName + errorMsg; } }
private static object GetValue(ExcelDataRow row, Type propType, string colName) { string val = row.DataCols.SingleOrDefault(c => c.ColName == colName)?.ColValue; if (!string.IsNullOrWhiteSpace(val)) { return(ExpressionMapper.ChangeType(val, propType)); } return(val); }
/// <summary> /// 将IRow转换为ExcelDataRow /// </summary> /// <typeparam name="TTemplate"></typeparam> /// <param name="row"></param> /// <param name="headerRow"></param> /// <returns></returns> public static ExcelDataRow Convert <TTemplate>(IRow row, ExcelHeaderRow headerRow) { Type type = typeof(TTemplate); ExcelDataRow dataRow = new ExcelDataRow() { DataCols = new List <ExcelDataCol>(), ErrorMsg = string.Empty, IsValid = true, RowIndex = row.RowNum }; //ICell cell; ExcelDataCol dataCol; string colName; string propertyName; string key; for (int i = 0; i < headerRow.Cells.Count; i++) { colName = headerRow?.Cells?.SingleOrDefault(h => h.ColIndex == i)?.ColName.Trim(); if (colName == null) { continue; } key = $"{type.FullName}_{i}"; if (Table[key] == null) { propertyName = type.GetProperties().ToList().FirstOrDefault(p => p.IsDefined(typeof(ColNameAttribute), false) && p.GetCustomAttribute <ColNameAttribute>()?.ColName == colName )?.Name; Table[key] = propertyName; } dataCol = new ExcelDataCol() { ColIndex = i, ColName = colName, PropertyName = Table[key]?.ToString(), RowIndex = row.RowNum, ColValue = row.GetCell(i) == null ? string.Empty : row.GetCell(i).GetStringValue() }; dataRow.DataCols.Add(dataCol); } return(dataRow); }
/// <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)); }
/// <summary> /// 直接反射 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="row"></param> /// <returns></returns> public static T Convert <T>(this ExcelDataRow row) { return(Convert <T>(row, GetValue)); }