/// <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 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);
        }
Exemplo n.º 4
0
        /// <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;

                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));
 }