コード例 #1
0
ファイル: Extension.cs プロジェクト: zmxGeorge/DbNet
        /// <summary>
        /// 将DataTable数据转换为List数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="table"></param>
        /// <returns></returns>
        public static List <T> ToList <T>(this DataTable table, string suffix = "") where T : class, new()
        {
            if (table == null)
            {
                return(new List <T>());
            }
            Type     tType = typeof(T);
            Delegate del   = null;

            if (!cache_del.TryGetValue(tType, out del))
            {
                PropertyInfo[] pinfos = tType.GetProperties();
                Dictionary <string, PropertyInfo> dic_p = new Dictionary <string, PropertyInfo>();
                foreach (var p in pinfos)
                {
                    DbParamterAttribute paramter_att = p.GetCustomAttribute <DbParamterAttribute>();
                    string keyName = p.Name;
                    if (paramter_att != null && !string.IsNullOrEmpty(paramter_att.Name))
                    {
                        keyName = paramter_att.Name;
                    }
                    if (dic_p.ContainsKey(keyName))
                    {
                        throw new Exception(string.Format("列名映射关系重复:{0}", keyName));
                    }
                    else
                    {
                        dic_p.Add(keyName, p);
                    }
                }
                MethodInfo    addMethod         = typeof(List <T>).GetMethod("Add", BindingFlags.Instance | BindingFlags.Public);
                DynamicMethod method            = new DynamicMethod(tType.FullName, typeof(List <T>), new Type[] { typeof(DataTable), typeof(string) }, true);
                var           gen               = method.GetILGenerator();
                LocalBuilder  countBulider      = gen.DeclareLocal(typeof(int));
                LocalBuilder  tableCountBulider = gen.DeclareLocal(typeof(int));
                LocalBuilder  rowBulider        = gen.DeclareLocal(typeof(DataRow));
                LocalBuilder  resultBulider     = gen.DeclareLocal(typeof(List <T>));
                LocalBuilder  newObjBulider     = gen.DeclareLocal(tType);
                LocalBuilder  columnBulider     = gen.DeclareLocal(typeof(DataColumnCollection));
                gen.Emit(OpCodes.Newobj, typeof(List <T>).GetConstructor(Type.EmptyTypes));
                gen.Emit(OpCodes.Stloc, resultBulider.LocalIndex);//new List
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Call, ColumnsInfo.GetGetMethod());
                gen.Emit(OpCodes.Stloc, columnBulider.LocalIndex);
                Dictionary <string, LocalBuilder> columnNameDic = new Dictionary <string, LocalBuilder>();
                foreach (string k in dic_p.Keys)
                {
                    if (!columnNameDic.ContainsKey(k))
                    {
                        LocalBuilder rBulider = gen.DeclareLocal(typeof(string));
                        gen.Emit(OpCodes.Ldarg_1);
                        gen.Emit(OpCodes.Ldstr, k);
                        gen.Emit(OpCodes.Call, StringConcat);
                        gen.Emit(OpCodes.Stloc, rBulider.LocalIndex);
                        columnNameDic.Add(k, rBulider);
                    }
                }
                gen.Emit(OpCodes.Ldc_I4_0);
                gen.Emit(OpCodes.Stloc, countBulider.LocalIndex);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Call, RowsInfo.GetGetMethod());
                gen.Emit(OpCodes.Call, CountInfo.GetGetMethod());
                gen.Emit(OpCodes.Stloc, tableCountBulider.LocalIndex);
                Label eachLabel  = gen.DefineLabel();
                Label emptyLabel = gen.DefineLabel();
                gen.Emit(OpCodes.Ldloc, tableCountBulider.LocalIndex);
                gen.Emit(OpCodes.Ldc_I4_0);
                gen.Emit(OpCodes.Ble, emptyLabel);
                gen.MarkLabel(eachLabel);//循环顶部标签
                LocalBuilder entityBulider = gen.DeclareLocal(typeof(T));
                gen.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
                gen.Emit(OpCodes.Stloc, entityBulider.LocalIndex);
                gen.Emit(OpCodes.Ldarg_0);
                gen.Emit(OpCodes.Ldloc, countBulider.LocalIndex);
                gen.Emit(OpCodes.Call, m_get_row_define);
                gen.Emit(OpCodes.Stloc, rowBulider.LocalIndex);
                foreach (var item in columnNameDic)
                {
                    var key = item.Key;
                    var p   = dic_p[key];
                    gen.Emit(OpCodes.Ldloc, entityBulider.LocalIndex);
                    gen.Emit(OpCodes.Ldloc, rowBulider.LocalIndex);
                    gen.Emit(OpCodes.Ldloc, item.Value.LocalIndex);
                    gen.Emit(OpCodes.Call, m_get_row_Value.MakeGenericMethod(new Type[] { p.PropertyType }));
                    gen.Emit(OpCodes.Call, p.GetSetMethod());
                }
                gen.Emit(OpCodes.Ldloc, resultBulider.LocalIndex);
                gen.Emit(OpCodes.Ldloc, entityBulider.LocalIndex);
                gen.Emit(OpCodes.Call, addMethod);
                gen.Emit(OpCodes.Ldloc, countBulider.LocalIndex);
                gen.Emit(OpCodes.Ldc_I4_1);
                gen.Emit(OpCodes.Add_Ovf);
                gen.Emit(OpCodes.Stloc, countBulider.LocalIndex);
                gen.Emit(OpCodes.Ldloc, countBulider.LocalIndex);
                gen.Emit(OpCodes.Ldloc, tableCountBulider.LocalIndex);
                //判断是否小于table.Rows.Count,是则调到循环顶部Label
                gen.Emit(OpCodes.Blt, eachLabel);
                gen.MarkLabel(emptyLabel);
                gen.Emit(OpCodes.Ldloc, resultBulider.LocalIndex);
                gen.Emit(OpCodes.Ret);
                del = method.CreateDelegate(typeof(ToTableList <T>));
                cache_del.TryAdd(tType, del);
            }
            return((del as ToTableList <T>)(table, suffix));
        }
コード例 #2
0
        /// <summary>
        /// 获取参数封装入集合
        /// </summary>
        /// <param name="paramterList"></param>
        /// <param name="gen"></param>
        /// <param name="paramterListBulider"></param>
        private static void GetParamters(List <Tuple <string, int, MethodInfo, Type> > outputParamters,
                                         ParameterInfo[] paramterList, ILGenerator gen, LocalBuilder paramterListBulider, bool use_cache, string sqlTextKey, out ParameterInfo scope_parameterInfo)
        {
            scope_parameterInfo = null;
            bool haschache_attr = paramterList.Any(x => x.GetCustomAttribute <DbCacheKeyAttribute>() != null);

            foreach (var paramter in paramterList)
            {
                if (!string.IsNullOrEmpty(sqlTextKey) && paramter.Name == sqlTextKey)
                {
                    //跳过指定sql语句的参数
                    continue;
                }
                Type pType = paramter.ParameterType;
                Type eType = pType.GetElementType();//若为ref或out参数则eType为其原来类型
                if (pType.GetInterface(SCOPE_ITEM) != null ||
                    (eType != null && eType.GetInterface(SCOPE_ITEM) != null))
                {
                    //IDbNetScope类型为事务处理变量,不能添加到参数中
                    scope_parameterInfo = paramter;
                    continue;
                }
                LocalBuilder           pTypeBulider = null;
                DbNetParamterDirection dir          = DbNetParamterDirection.Input;
                CacheKeyType           cacheKeyType = CacheKeyType.None;
                if (use_cache)
                {
                    cacheKeyType = CacheKeyType.Bind;
                    if (haschache_attr)
                    {
                        cacheKeyType = CacheKeyType.None;
                    }
                    var cache_attr = paramter.GetCustomAttribute <DbCacheKeyAttribute>();
                    if (cache_attr != null)
                    {
                        cacheKeyType = CacheKeyType.Bind;
                    }
                }
                if (!paramter.IsOut &&
                    !pType.IsByRef)
                {
                    pTypeBulider = gen.DeclareLocal(pType);
                    gen.Emit(OpCodes.Ldarg, paramter.Position + 1);
                }
                else
                {
                    dir          = DbNetParamterDirection.InputAndOutPut;
                    pTypeBulider = gen.DeclareLocal(eType);
                    if (pType.IsByRef)
                    {
                        //获取ref参数的值
                        gen.Emit(OpCodes.Ldarg, paramter.Position + 1);
                        GetRef(gen, pTypeBulider.LocalType);
                    }
                }
                gen.Emit(OpCodes.Stloc, pTypeBulider);
                if (pTypeBulider.LocalType.IsClass)
                {
                    Label isNullLabel = gen.DefineLabel();
                    gen.Emit(OpCodes.Ldloc, pTypeBulider);
                    gen.Emit(OpCodes.Ldnull);
                    gen.Emit(OpCodes.Ceq);
                    gen.Emit(OpCodes.Brfalse, isNullLabel);
                    gen.Emit(OpCodes.Call, MethodHelper.defaultMethod.MakeGenericMethod(pTypeBulider.LocalType));
                    gen.Emit(OpCodes.Stloc, pTypeBulider);
                    gen.MarkLabel(isNullLabel);
                }
                if (paramter.IsOut || pType.IsByRef)
                {
                    //输出参数获取下阶段备用
                    outputParamters.Add(new Tuple <string, int, MethodInfo, Type>(paramter.Name, paramter.Position + 1, null, eType));
                }
                if (pTypeBulider.LocalType == typeof(string) ||
                    pTypeBulider.LocalType.IsValueType ||
                    pTypeBulider.LocalType.IsArray)
                {
                    //添加结构体或者string到集合
                    gen.Emit(OpCodes.Ldloc, paramterListBulider);
                    gen.Emit(OpCodes.Ldstr, paramter.Name);
                    gen.Emit(OpCodes.Ldloc, pTypeBulider);
                    gen.Emit(OpCodes.Ldc_I4, (int)dir);
                    gen.Emit(OpCodes.Ldc_I4, paramter.Position);
                    gen.Emit(OpCodes.Ldc_I4, (int)SourceType.FromArg);
                    gen.Emit(OpCodes.Ldc_I4, (int)cacheKeyType);
                    gen.Emit(OpCodes.Call, MethodHelper.paramterMethod.MakeGenericMethod(pTypeBulider.LocalType));
                }
                else
                {
                    //如果参数是类则需进一步处理
                    var pinfo        = pTypeBulider.LocalType.GetProperties();
                    var cache_attr_c = paramter.GetCustomAttribute <DbCacheKeyAttribute>();
                    foreach (var p in pinfo)
                    {
                        DbParamterAttribute attr_p = p.GetCustomAttribute <DbParamterAttribute>(true);
                        bool   except = false;
                        string name   = string.Empty;
                        DbNetParamterDirection pdir           = DbNetParamterDirection.Input;
                        CacheKeyType           p_cacheKeyType = CacheKeyType.None;
                        if (use_cache)
                        {
                            p_cacheKeyType = CacheKeyType.Bind;
                            if (haschache_attr)
                            {
                                p_cacheKeyType = CacheKeyType.None;
                            }
                            if (cache_attr_c != null)
                            {
                                p_cacheKeyType = CacheKeyType.Bind;
                            }
                            if (attr_p != null && attr_p.CacheKey != CacheKeyType.Default)
                            {
                                p_cacheKeyType = attr_p.CacheKey;
                            }
                        }
                        if (paramter.IsOut)
                        {
                            //输出参数获取下阶段备用
                            outputParamters.Add(new Tuple <string, int, MethodInfo, Type>(paramter.Name, paramter.Position + 1, p.GetSetMethod(), p.PropertyType));
                            pdir = DbNetParamterDirection.Output;
                        }
                        else if (pType.IsByRef)
                        {
                            //输出参数获取下阶段备用
                            outputParamters.Add(new Tuple <string, int, MethodInfo, Type>(paramter.Name, paramter.Position + 1, p.GetSetMethod(), p.PropertyType));
                            pdir = DbNetParamterDirection.InputAndOutPut;
                        }
                        if (attr_p != null)
                        {
                            except = attr_p.Except;
                            name   = attr_p.Name;
                            pdir   = attr_p.ParameterDirection;
                        }
                        if (string.IsNullOrEmpty(name))
                        {
                            name = p.Name;
                        }
                        if (!except)
                        {
                            gen.Emit(OpCodes.Ldloc, paramterListBulider);
                            gen.Emit(OpCodes.Ldstr, name);
                            gen.Emit(OpCodes.Ldloc, pTypeBulider);
                            gen.Emit(OpCodes.Call, p.GetGetMethod());
                            gen.Emit(OpCodes.Ldc_I4, (int)pdir);
                            gen.Emit(OpCodes.Ldc_I4, paramter.Position);
                            gen.Emit(OpCodes.Ldc_I4, (int)SourceType.FromClass);
                            gen.Emit(OpCodes.Ldc_I4, (int)p_cacheKeyType);
                            gen.Emit(OpCodes.Call, MethodHelper.paramterMethod.MakeGenericMethod(p.PropertyType));
                        }
                    }
                }
            }
        }