示例#1
0
        /// <summary>
        /// 创建路由获取数据库连接以及数据库提供程序
        /// </summary>
        /// <param name="configuration"></param>
        /// <param name="route_name"></param>
        /// <param name="function_type"></param>
        /// <param name="m"></param>
        /// <param name="m_route_type"></param>
        /// <param name="gen"></param>
        /// <param name="sqlConnection_bulider"></param>
        /// <param name="dbNetProvider"></param>
        /// <param name="paramterBulider"></param>
        private static void MapRouteAndProvider(DbNetConfiguration configuration, string route_name, Type function_type, MethodInfo m, Type m_route_type, ILGenerator gen, LocalBuilder sqlConnection_bulider, LocalBuilder dbNetProvider, LocalBuilder paramterBulider)
        {
            //执行路由中的方法RouteDbConnection
            LocalBuilder route_bulider = gen.DeclareLocal(m_route_type);

            gen.Emit(OpCodes.Newobj, m_route_type.GetConstructor(Type.EmptyTypes));
            gen.Emit(OpCodes.Stloc, route_bulider);
            gen.Emit(OpCodes.Ldloc, route_bulider);
            gen.Emit(OpCodes.Ldstr, route_name);
            gen.Emit(OpCodes.Ldstr, function_type.Name);
            gen.Emit(OpCodes.Ldstr, m.Name);
            gen.Emit(OpCodes.Ldloc, paramterBulider);
            gen.Emit(OpCodes.Ldloca, dbNetProvider.LocalIndex);
            gen.Emit(OpCodes.Call, MethodHelper.dbNetRouteMethod);
            gen.Emit(OpCodes.Stloc, sqlConnection_bulider);
            if (configuration.DbProvider != null)
            {
                //执行路由结束,判断返回的数据库提供程序是否为null,若为null则根据默认设置创建数据库提供程序
                Label dbProviderNullLabel = gen.DefineLabel();
                gen.Emit(OpCodes.Ldloc, dbNetProvider);
                gen.Emit(OpCodes.Ldnull);
                gen.Emit(OpCodes.Ceq);
                gen.Emit(OpCodes.Brfalse, dbProviderNullLabel);
                //创建默认的提供程序
                gen.Emit(OpCodes.Newobj, configuration.DbProvider.GetConstructor(Type.EmptyTypes));
                gen.Emit(OpCodes.Stloc, dbNetProvider);
                gen.MarkLabel(dbProviderNullLabel);
            }
            //若不存在默认设置则抛出异常
            Label dbProviderNullLabel_two = gen.DefineLabel();

            gen.Emit(OpCodes.Ldloc, dbNetProvider);
            gen.Emit(OpCodes.Ldnull);
            gen.Emit(OpCodes.Ceq);
            gen.Emit(OpCodes.Brfalse, dbProviderNullLabel_two);
            gen.ThrowException(typeof(DbProviderNotFoundException));
            gen.MarkLabel(dbProviderNullLabel_two);
        }
示例#2
0
 /// <summary>
 /// 注册接口
 /// </summary>
 /// <typeparam name="TFunction">接口类型</typeparam>
 /// <param name="configuration">配置项</param>
 public abstract void RegistFunction <TFunction>(DbNetConfiguration configuration) where TFunction : IDbFunction;
示例#3
0
        public override void RegistFunction <TFunction>(DbNetConfiguration configuration)
        {
            string route_name    = string.Empty;
            Type   function_type = typeof(TFunction);
            //获取接口类型中设定的路由
            DbRouteAttribute routeAttribute = function_type.GetCustomAttribute <DbRouteAttribute>(true);
            Type             dbroute_type   = null;

            if (configuration.RouteCollection.ContainsKey("*"))
            {
                //默认路由 关键字为*
                dbroute_type = configuration.RouteCollection["*"];
            }
            if (routeAttribute != null)
            {
                if (!configuration.RouteCollection.ContainsKey(routeAttribute.Name))
                {
                    throw new ArgumentException("不存在路由:" + routeAttribute.Name);
                }
                //若接口类型中设定的路由存在,则设置为该路由
                dbroute_type = configuration.RouteCollection[routeAttribute.Name];
                route_name   = routeAttribute.Name;
            }
            var baseM   = function_type.GetInterfaces().SelectMany(x => x.GetMethods(BindingFlags.Public | BindingFlags.Instance)).ToList();
            var methods = function_type.GetMethods(BindingFlags.Public | BindingFlags.Instance);

            methods = baseM.Concat(methods).ToArray();
            //创建实现类型
            TypeBuilder tb = module_bulider.DefineType(string.Format(KEY_FORMAT, function_type.Name, function_type.Namespace + "."), TypeAttributes.Class | TypeAttributes.Public, typeof(DbContext));

            tb.AddInterfaceImplementation(function_type);
            foreach (var m in methods)
            {
                //路由类型
                Type                m_route_type = dbroute_type;
                DbRouteAttribute    m_route      = m.GetCustomAttribute <DbRouteAttribute>(true);
                DbFunctionAttribute m_fun        = m.GetCustomAttribute <DbFunctionAttribute>(true);
                if (m_route != null)
                {
                    if (!configuration.RouteCollection.ContainsKey(m_route.Name))
                    {
                        throw new ArgumentException("不存在路由:" + m_route.Name);
                    }
                    //判断接口方法中是否存在路由,如果有则设定为该路由类型
                    m_route_type = configuration.RouteCollection[m_route.Name];
                }
                if (m_route_type == null)
                {
                    throw new ArgumentException(string.Format("方法:{0} 未设置任何路由", m.Name));
                }

                #region IL代码开始
                var paramterList = m.GetParameters();
                var tm           = tb.DefineMethod(m.Name, MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.RTSpecialName, CallingConventions.HasThis,
                                                   m.ReturnType, paramterList.Select(x => x.ParameterType).ToArray());
                if (paramterList.Count(x => (x.ParameterType.GetInterface(SCOPE_ITEM) != null ||
                                             (x.ParameterType.GetElementType() != null && x.ParameterType.GetElementType().GetInterface(SCOPE_ITEM) != null))) > 1)
                {
                    throw new Exception("参数中实现IDbNetScope接口类型的参数不能超过一个");
                }
                //定义方法实现内容
                ILGenerator gen         = tm.GetILGenerator();
                ExecuteType executeType = ExecuteType.Default;
                bool        user_cache  = false;
                bool        user_tran   = false;
                if (m_fun != null)
                {
                    executeType = m_fun.ExecuteType;
                    GetExecuteType(m, ref executeType);
                    user_cache = m_fun.UserCache;
                    user_tran  = m_fun.UseTransaction;
                }
                if (user_cache && user_tran)
                {
                    throw new ArgumentException(string.Format("缓存和事务不能被同时使用,接口:{0} 方法:{1}", function_type.Name, m.Name));
                }
                LocalBuilder result_builder        = gen.DeclareLocal(m.ReturnType);                    //定义返回变量
                LocalBuilder sqlText_bulider       = gen.DeclareLocal(typeof(string));                  //定义Sql语句变量
                LocalBuilder sqlConnection_bulider = gen.DeclareLocal(typeof(string));                  //定义数据库连接变量
                LocalBuilder cacheKey_bulider      = gen.DeclareLocal(typeof(string));                  //定义缓存键变量
                LocalBuilder cacheItem_bulider     = gen.DeclareLocal(typeof(ISQLCacheItem));           //定义缓存对象变量
                LocalBuilder netScope_bulider      = gen.DeclareLocal(typeof(IDbNetScope));             //定义NetScope
                LocalBuilder hasCache_bulider      = gen.DeclareLocal(typeof(bool));                    //定义是否存在缓存变量
                LocalBuilder dbNetProvider         = gen.DeclareLocal(typeof(IDbNetProvider));          //定义数据库提供程序变量
                LocalBuilder cacheProvider         = gen.DeclareLocal(typeof(IDbNetCacheProvider));     //定义缓存提供程序变量
                LocalBuilder exceptionBulider      = gen.DeclareLocal(typeof(Exception));               //定义异常变量,使用try catch
                LocalBuilder paramterBulider       = gen.DeclareLocal(typeof(DbNetParamterCollection)); //定义封装参数的集合变量
                LocalBuilder hasCacheBulider       = gen.DeclareLocal(typeof(bool));                    //定义是否存在缓存的变量
                LocalBuilder commandBulider        = gen.DeclareLocal(typeof(DbNetCommand));            //定义是否存在缓存的变量

                Label end_label = gen.DefineLabel();                                                    //指向执行结束的标签

                var try_label = gen.BeginExceptionBlock();                                              //try开始
                //初始化定义缓存是否存在的变量
                gen.Emit(OpCodes.Ldc_I4_0);
                gen.Emit(OpCodes.Stloc, hasCacheBulider);

                if (user_cache)
                {
                    //若存在缓存,创建缓存提供程序
                    gen.Emit(OpCodes.Newobj, configuration.CacheProviderType.GetConstructor(Type.EmptyTypes));
                    gen.Emit(OpCodes.Stloc, cacheProvider);
                }

                //初始化参数集合
                gen.Emit(OpCodes.Newobj, typeof(DbNetParamterCollection).GetConstructor(Type.EmptyTypes));
                gen.Emit(OpCodes.Stloc, paramterBulider);
                ParameterInfo scopeParemterInfo = null;
                string        sqlTextKey        = null;
                if (m_fun != null)
                {
                    sqlTextKey = m_fun.SqlTextKey;
                }
                List <Tuple <string, int, MethodInfo, Type> > outputParamters = new List <Tuple <string, int, MethodInfo, Type> >();
                GetParamters(outputParamters, paramterList, gen, paramterBulider, user_cache, sqlTextKey, out scopeParemterInfo);

                //sql语句处理
                string sqlText = m.Name;
                if (m_fun != null && !string.IsNullOrEmpty(m_fun.SqlText))
                {
                    sqlText = m_fun.SqlText;
                    gen.Emit(OpCodes.Ldstr, sqlText);
                }
                else if (m_fun != null && !string.IsNullOrEmpty(sqlTextKey))
                {
                    var paramter = paramterList.FirstOrDefault(x => x.Name == sqlTextKey);
                    if (paramter == null)
                    {
                        throw new Exception("未能找到指定sql语句的参数,名称:" + sqlTextKey);
                    }
                    if (paramter.ParameterType != typeof(string))
                    {
                        throw new Exception("指定sql语句的参数类型必须为string");
                    }
                    gen.Emit(OpCodes.Ldarg, paramter.Position + 1);
                }
                gen.Emit(OpCodes.Stloc, sqlText_bulider);
                MapRouteAndProvider(configuration, route_name, function_type, m, m_route_type, gen, sqlConnection_bulider, dbNetProvider, paramterBulider);
                SetCache(m.ReturnType, function_type.Name, m.Name, sqlText_bulider, gen, user_cache, result_builder, cacheKey_bulider,
                         cacheItem_bulider, cacheProvider, paramterBulider, hasCacheBulider, end_label);
                string commandType = string.Empty;
                if (m_fun != null)
                {
                    commandType = m_fun.CommandType;
                }
                //建立Command
                gen.Emit(OpCodes.Ldloc, sqlText_bulider);
                gen.Emit(OpCodes.Ldloc, sqlConnection_bulider);
                gen.Emit(OpCodes.Ldloc, paramterBulider);
                gen.Emit(OpCodes.Ldstr, commandType);
                if (m_fun == null || string.IsNullOrEmpty(m_fun.IsolationLevel))
                {
                    gen.Emit(OpCodes.Ldsfld, MethodHelper.none_level);
                }
                else
                {
                    gen.Emit(OpCodes.Ldstr, m_fun.IsolationLevel);
                    gen.Emit(OpCodes.Newobj, MethodHelper.level_bulid);
                }
                gen.Emit(OpCodes.Newobj, MethodHelper.command_bulid_Method);
                gen.Emit(OpCodes.Stloc, commandBulider);
                //处理NetScope
                if (scopeParemterInfo != null)
                {
                    gen.Emit(OpCodes.Ldarg, scopeParemterInfo.Position + 1);
                    if (scopeParemterInfo.ParameterType.IsByRef)
                    {
                        gen.Emit(OpCodes.Ldind_Ref);
                    }
                    gen.Emit(OpCodes.Stloc, netScope_bulider);
                }
                //执行命令
                LocalBuilder dbNetResultBulider = gen.DeclareLocal(typeof(DbNetResult));
                gen.Emit(OpCodes.Ldloc, dbNetProvider);
                gen.Emit(OpCodes.Ldloc, commandBulider);
                gen.Emit(OpCodes.Ldloca, netScope_bulider);
                gen.Emit(OpCodes.Ldc_I4, (int)executeType);
                gen.Emit(OpCodes.Call, MethodHelper.db_exec_Method);
                gen.Emit(OpCodes.Stloc, dbNetResultBulider);
                gen.Emit(OpCodes.Ldloc, dbNetResultBulider);
                Type rType = m.ReturnType;
                if (rType.IsValueType || rType == typeof(string) ||
                    (rType.IsArray && rType.GetElementType() != null && rType.GetElementType().IsValueType))
                {
                    gen.Emit(OpCodes.Call, MethodHelper.get_result_method.MakeGenericMethod(rType));
                }
                else
                {
                    gen.Emit(OpCodes.Call, MethodHelper.get_result_method.MakeGenericMethod(typeof(DataSet)));
                    if (rType != typeof(DataSet) &&
                        rType != typeof(DataTable))
                    {
                        //需要做List转换的类型
                        if (rType.IsArray)
                        {
                            gen.Emit(OpCodes.Call, MethodHelper.to_array_Method.MakeGenericMethod(rType.GetElementType()));
                        }
                        else if (rType.GetInterface(typeof(System.Collections.IList).FullName) != null)
                        {
                            gen.Emit(OpCodes.Call, MethodHelper.to_list_Method.MakeGenericMethod(rType.GetGenericArguments()));
                        }
                        else if (rType.IsClass)
                        {
                            gen.Emit(OpCodes.Call, MethodHelper.to_object_Method.MakeGenericMethod(rType));
                        }
                    }
                }
                gen.Emit(OpCodes.Stloc, result_builder);
                if (scopeParemterInfo == null)
                {
                    //如果不存在DbNetScope参数的话,DbNetScope范围会视作只在该方法内部执行
                    //故会调用Dispose
                    gen.Emit(OpCodes.Ldloc, netScope_bulider);
                    gen.Emit(OpCodes.Call, MethodHelper.dispos_Method);
                }
                //若存在scope输出参数则赋值
                if (scopeParemterInfo != null &&
                    (scopeParemterInfo.IsOut ||
                     scopeParemterInfo.ParameterType.IsByRef))
                {
                    gen.Emit(OpCodes.Ldarg, scopeParemterInfo.Position + 1);
                    gen.Emit(OpCodes.Ldloc, netScope_bulider);
                    gen.Emit(OpCodes.Stind_Ref);
                }
                //缓存添加
                if (user_cache)
                {
                    int dtime = 0;
                    int ntime = 0;
                    if (m_fun != null)
                    {
                        dtime = m_fun.DuringTime;
                        ntime = m_fun.CacheTime;
                    }
                    gen.Emit(OpCodes.Ldloc, commandBulider);
                    gen.Emit(OpCodes.Ldloc, result_builder);
                    gen.Emit(OpCodes.Newobj, typeof(SQLCacheItem <>).MakeGenericType(m.ReturnType).GetConstructor(new Type[] { typeof(DbNetCommand), m.ReturnType }));
                    gen.Emit(OpCodes.Stloc, cacheItem_bulider);
                    gen.Emit(OpCodes.Ldloc, cacheProvider);
                    gen.Emit(OpCodes.Ldloc, cacheKey_bulider);
                    gen.Emit(OpCodes.Ldloc, cacheItem_bulider);
                    gen.Emit(OpCodes.Ldc_I4, ntime);
                    gen.Emit(OpCodes.Ldc_I4, dtime);
                    gen.Emit(OpCodes.Call, MethodHelper.cache_addCacheMethod);
                }
                gen.BeginCatchBlock(typeof(Exception));
                //catch处理
                if (scopeParemterInfo != null &&
                    (scopeParemterInfo.IsOut || scopeParemterInfo.ParameterType.IsByRef))
                {
                    gen.Emit(OpCodes.Ldarg, scopeParemterInfo.Position + 1);
                    gen.Emit(OpCodes.Ldloc, netScope_bulider);
                    gen.Emit(OpCodes.Stind_Ref);
                }
                gen.Emit(OpCodes.Stloc, exceptionBulider);
                gen.Emit(OpCodes.Ldloc, exceptionBulider);
                gen.Emit(OpCodes.Call, MethodHelper.exceptionMethod);
                gen.EndExceptionBlock();

                gen.MarkLabel(end_label);

                //若有out参数返回值在此处理
                foreach (var item in outputParamters)
                {
                    string     name    = item.Item1;
                    int        index   = item.Item2;
                    MethodInfo pro_set = item.Item3;
                    Type       tType   = item.Item4;
                    if (pro_set == null)
                    {
                        gen.Emit(OpCodes.Ldarg, index);
                        gen.Emit(OpCodes.Ldloc, paramterBulider);
                        gen.Emit(OpCodes.Ldstr, name);
                        gen.Emit(OpCodes.Call, MethodHelper.getValueMethod.MakeGenericMethod(tType));
                        SetRef(gen, tType);
                    }
                    else
                    {
                        gen.Emit(OpCodes.Ldarg, index);
                        gen.Emit(OpCodes.Ldloc, paramterBulider);
                        gen.Emit(OpCodes.Ldstr, name);
                        gen.Emit(OpCodes.Call, MethodHelper.getValueMethod.MakeGenericMethod(tType));
                        gen.Emit(OpCodes.Call, pro_set);
                    }
                }

                #region 返回结果
                if (m.ReturnType != null)
                {
                    gen.Emit(OpCodes.Ldloc, result_builder);
                }
                gen.Emit(OpCodes.Ret);
                #endregion

                #endregion
            }
            var t = tb.CreateType();
            cache_imp.TryAdd(function_type, Activator.CreateInstance(t));
        }