Esempio n. 1
0
        private void BuildMethod(MethodInfo methodInfo, bool IsGloab)
        {
            string methodName = methodInfo.Name;

            ParameterInfo[] parameterInfos = methodInfo.GetParameters();
            Type            returnType     = methodInfo.ReturnType;

            MethodBuilder methodBuilder = null;

            methodBuilder = _typeBuilder.DefineMethod(methodName,
                                                      MethodAttributes.Public | MethodAttributes.Virtual,
                                                      returnType,
                                                      parameterInfos.Select(pi => pi.ParameterType).ToArray());

            var   il                      = methodBuilder.GetILGenerator();
            Label castPerSuccess          = il.DefineLabel();
            Label castArroundSuccess      = il.DefineLabel();
            Label castAfterArroundSuccess = il.DefineLabel();
            Label castPostSuccess         = il.DefineLabel();

            Label castExSuccess = il.DefineLabel();

            #region Decalre InvokeContext

            Type contextType  = typeof(InvokeContext);
            var  contextLocal = il.DeclareLocal(contextType);
            il.Emit(OpCodes.Newobj, contextType.GetConstructor(Type.EmptyTypes));
            il.Emit(OpCodes.Stloc, contextLocal);

            // set method name
            il.Emit(OpCodes.Ldloc, contextLocal);
            il.Emit(OpCodes.Ldstr, methodName);
            il.Emit(OpCodes.Call, contextType.GetMethod("SetMethod", BindingFlags.Public | BindingFlags.Instance));

            #endregion

            #region Decalre result

            LocalBuilder resultLocal = null;

            if (returnType != typeof(void))
            {
                resultLocal = il.DeclareLocal(returnType);
                if (returnType.IsValueType)
                {
                    il.Emit(OpCodes.Ldstr, returnType.FullName);
                    il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetType", new Type[] { typeof(string) }));
                    il.Emit(OpCodes.Call, typeof(Activator).GetMethod("CreateInstance", new Type[] { typeof(Type) }));
                }
                else
                {
                    il.Emit(OpCodes.Ldnull);
                }

                il.Emit(OpCodes.Stloc, resultLocal);
            }

            #endregion

            #region Declare Exception

            var exceptionLocal = il.DeclareLocal(typeof(Exception));
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Stloc, exceptionLocal);

            #endregion

            #region Invoke PreInvoke

            #region Set parameter to InvkeContext

            for (int i = 1; i <= parameterInfos.Length; i++)
            {
                il.Emit(OpCodes.Ldloc, contextLocal);
                il.Emit(OpCodes.Ldarg, i);
                if (parameterInfos[i - 1].ParameterType.IsValueType)
                {
                    il.Emit(OpCodes.Box, parameterInfos[i - 1].ParameterType);
                }
                il.Emit(OpCodes.Call, contextType.GetMethod("SetParameter", BindingFlags.Public | BindingFlags.Instance));
            }

            #endregion
            //var classInfoLocal1 = _realProxyType.GetType();
            //ArroundAttribute preAspectLocal1 =
            //    (ArroundAttribute)Attribute.GetCustomAttribute(classInfoLocal1, typeof(ArroundAttribute));

            /*
             * C# 代码
             * MethodInfo classInfoLocal = _realProxyField.GetType().GetMethod("methodName");
             * ArroundAttribute preAspectLocal =
             *      (ArroundAttribute)Attribute.GetCustomAttribute(classInfoLocal, typeof(ArroundAttribute))
             *
             * if (preAspectLocal != null)
             * {
             *      preAspectLocal.Action(contextLocal);
             * }
             *
             */

            var          classInfoLocal     = il.DeclareLocal(_realProxyField.GetType());
            LocalBuilder arrountAspectLocal = il.DeclareLocal(typeof(ArroundAttribute));
            if (IsGloab)
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, _realProxyField);
                il.Emit(OpCodes.Callvirt,
                        typeof(System.Object).GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance));
                //il.Emit(OpCodes.Ldstr, methodName);
                //il.Emit(OpCodes.Callvirt,
                //        typeof(System.Type).GetMethod("GetMethod", new Type[] { typeof(string) }));
                il.Emit(OpCodes.Stloc, classInfoLocal);

                il.Emit(OpCodes.Ldloc, classInfoLocal);
            }
            else
            {
                classInfoLocal = il.DeclareLocal(typeof(MethodInfo));
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, _realProxyField);
                il.Emit(OpCodes.Callvirt,
                        typeof(System.Object).GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance));
                il.Emit(OpCodes.Ldstr, methodName);
                il.Emit(OpCodes.Callvirt,
                        typeof(System.Type).GetMethod("GetMethod", new Type[] { typeof(string) }));
                il.Emit(OpCodes.Stloc, classInfoLocal);

                il.Emit(OpCodes.Ldloc, classInfoLocal);
            }
            il.Emit(OpCodes.Ldtoken, typeof(ArroundAttribute));
            //generator.Emit(OpCodes.Ldloca, )
            il.Emit(OpCodes.Call,
                    typeof(System.Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(System.RuntimeTypeHandle) }));
            il.Emit(OpCodes.Call,
                    typeof(System.Attribute).GetMethod("GetCustomAttribute",
                                                       new Type[]
            {
                typeof(System.Reflection.MemberInfo), typeof(System.Type)
            }));
            il.Emit(OpCodes.Castclass, typeof(ArroundAttribute));
            il.Emit(OpCodes.Stloc, arrountAspectLocal);

            il.Emit(OpCodes.Ldloc, arrountAspectLocal);

            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Brtrue_S, castArroundSuccess);
            il.Emit(OpCodes.Ldloc, arrountAspectLocal);
            il.Emit(OpCodes.Ldloc, contextLocal);
            il.Emit(OpCodes.Callvirt,
                    typeof(ArroundAttribute).GetMethod("BeginAction", new Type[] { typeof(InvokeContext) }));

            il.MarkLabel(castArroundSuccess);

            #endregion

            #region  pre
            var preAspectLocal = il.DeclareLocal(typeof(PostAspectAttribute));

            /*
             * generator.Emit(OpCodes.Ldarg_0);
             * generator.Emit(OpCodes.Ldfld, _realProxyField);
             * generator.Emit(OpCodes.Callvirt, typeof(System.Object).GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance));
             * generator.Emit(OpCodes.Ldstr, methodName);
             * generator.Emit(OpCodes.Callvirt,
             *  typeof(System.Type).GetMethod("GetMethod", new Type[] { typeof(string) }));
             * generator.Emit(OpCodes.Stloc, classInfoLocal);
             */

            il.Emit(OpCodes.Ldloc, classInfoLocal);
            il.Emit(OpCodes.Ldtoken, typeof(PreAspectAttribute));
            //generator.Emit(OpCodes.Ldloca, )
            il.Emit(OpCodes.Call,
                    typeof(System.Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(System.RuntimeTypeHandle) }));
            il.Emit(OpCodes.Call,
                    typeof(System.Attribute).GetMethod("GetCustomAttribute",
                                                       new Type[] { typeof(System.Reflection.MethodInfo), typeof(System.Type) }));
            il.Emit(OpCodes.Castclass, typeof(PreAspectAttribute));
            il.Emit(OpCodes.Stloc, preAspectLocal);

            il.Emit(OpCodes.Ldloc, preAspectLocal);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Brtrue_S, castPerSuccess);
            il.Emit(OpCodes.Ldloc, preAspectLocal);
            il.Emit(OpCodes.Ldloc, contextLocal);
            il.Emit(OpCodes.Callvirt,
                    typeof(AspectAttribute).GetMethod("Action", new Type[] { typeof(InvokeContext) }));

            il.MarkLabel(castPerSuccess);
            #endregion

            #region Begin Exception Block

            Label exLbl = il.BeginExceptionBlock();

            #endregion

            #region Invoke

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldfld, _realProxyField);
            for (int i = 1; i <= parameterInfos.Length; i++)
            {
                il.Emit(OpCodes.Ldarg, i);
            }

            il.Emit(OpCodes.Call, _realProxyType.GetMethod(methodName, BindingFlags.Public | BindingFlags.Instance));
            if (typeof(void) != returnType)
            {
                il.Emit(OpCodes.Stloc, resultLocal);
            }

            #endregion

            #region Invoke PostInovke

            #region Set result to InvkeContext

            il.Emit(OpCodes.Ldloc, contextLocal);
            // load parameter
            if (typeof(void) != returnType)
            {
                il.Emit(OpCodes.Ldloc, resultLocal);
                if (returnType.IsValueType)
                {
                    il.Emit(OpCodes.Box, returnType);
                }
            }
            else
            {
                il.Emit(OpCodes.Ldnull);
            }
            il.Emit(OpCodes.Call, contextType.GetMethod("SetResult", BindingFlags.Public | BindingFlags.Instance));

            #endregion

            #region Invoke PostInovke

            #region Set result to InvkeContext

            il.Emit(OpCodes.Ldloc, contextLocal);
            // load parameter
            if (typeof(void) != returnType)
            {
                il.Emit(OpCodes.Ldloc, resultLocal);
                if (returnType.IsValueType)
                {
                    il.Emit(OpCodes.Box, returnType);
                }
            }
            else
            {
                il.Emit(OpCodes.Ldnull);
            }
            il.Emit(OpCodes.Call, contextType.GetMethod("SetResult", BindingFlags.Public | BindingFlags.Instance));

            #endregion

            /*
             * C# 代码
             * MethodInfo classInfoLocal = _realProxyField.GetType().GetMethod("methodName");
             * PostAspectAttribute postAspectLocal =
             *      (PostAspectAttribute)Attribute.GetCustomAttribute(classInfoLocal, typeof(PostAspectAttribute))
             *
             * if (postAspectLocal != null)
             * {
             *      postAspectLocal.Action(contextLocal);
             * }
             *
             */
            // get post aspect if has
            //var classInfoLocal = generator.DeclareLocal(typeof(System.Reflection.MethodInfo));
            var postAspectLocal = il.DeclareLocal(typeof(PostAspectAttribute));

            /*
             * generator.Emit(OpCodes.Ldarg_0);
             * generator.Emit(OpCodes.Ldfld, _realProxyField);
             * generator.Emit(OpCodes.Callvirt, typeof(System.Object).GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance));
             * generator.Emit(OpCodes.Ldstr, methodName);
             * generator.Emit(OpCodes.Callvirt,
             *  typeof(System.Type).GetMethod("GetMethod", new Type[] { typeof(string) }));
             * generator.Emit(OpCodes.Stloc, classInfoLocal);
             */

            il.Emit(OpCodes.Ldloc, classInfoLocal);
            il.Emit(OpCodes.Ldtoken, typeof(PostAspectAttribute));
            //generator.Emit(OpCodes.Ldloca, )
            il.Emit(OpCodes.Call,
                    typeof(System.Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(System.RuntimeTypeHandle) }));
            il.Emit(OpCodes.Call,
                    typeof(System.Attribute).GetMethod("GetCustomAttribute",
                                                       new Type[] { typeof(System.Reflection.MethodInfo), typeof(System.Type) }));
            il.Emit(OpCodes.Castclass, typeof(PostAspectAttribute));
            il.Emit(OpCodes.Stloc, postAspectLocal);

            il.Emit(OpCodes.Ldloc, postAspectLocal);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Brtrue_S, castPostSuccess);
            il.Emit(OpCodes.Ldloc, postAspectLocal);
            il.Emit(OpCodes.Ldloc, contextLocal);
            il.Emit(OpCodes.Callvirt,
                    typeof(AspectAttribute).GetMethod("Action", new Type[] { typeof(InvokeContext) }));

            il.MarkLabel(castPostSuccess);

            #endregion

            /*
             * C# 代码
             * MethodInfo classInfoLocal = _realProxyField.GetType().GetMethod("methodName");
             * ArroundAttribute postAspectLocal =
             *      (ArroundAttribute)Attribute.GetCustomAttribute(classInfoLocal, typeof(ArroundAttribute))
             *
             * if (postAspectLocal != null)
             * {
             *      postAspectLocal.Action(contextLocal);
             * }
             *
             */


            il.Emit(OpCodes.Ldloc, arrountAspectLocal);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Brtrue_S, castAfterArroundSuccess);
            il.Emit(OpCodes.Ldloc, arrountAspectLocal);
            il.Emit(OpCodes.Ldloc, contextLocal);
            il.Emit(OpCodes.Callvirt,
                    typeof(ArroundAttribute).GetMethod("EndAction", new Type[] { typeof(InvokeContext) }));

            il.MarkLabel(castAfterArroundSuccess);

            #endregion

            #region Catch Block

            il.BeginCatchBlock(typeof(Exception));

            il.Emit(OpCodes.Stloc, exceptionLocal);
            il.Emit(OpCodes.Ldloc, contextLocal);
            il.Emit(OpCodes.Ldloc, exceptionLocal);
            il.Emit(OpCodes.Call, contextType.GetMethod("SetError", BindingFlags.Public | BindingFlags.Instance));

            /*
             * C# 代码
             * MethodInfo classInfoLocal = _realProxyField.GetType().GetMethod("methodName");
             * ExceptionAspectAttribute exAspectLocal =
             *      (ExceptionAspectAttribute)Attribute.GetCustomAttribute(classInfoLocal, typeof(ExceptionAspectAttribute))
             *
             * if (exAspectLocal != null)
             * {
             *      exAspectLocal.Action(contextLocal);
             * }
             *
             */
            // get exception aspect if has
            //var classInfoLocal = generator.DeclareLocal(typeof(System.Reflection.MethodInfo));
            var exAspectLocal = il.DeclareLocal(typeof(ArroundAttribute));

            /*
             * il.Emit(OpCodes.Ldarg_0);
             * il.Emit(OpCodes.Ldfld, _realProxyField);
             * il.Emit(OpCodes.Callvirt, typeof(System.Object).GetMethod("GetType", BindingFlags.Public | BindingFlags.Instance));
             * il.Emit(OpCodes.Ldstr, methodName);
             * il.Emit(OpCodes.Callvirt,
             *  typeof(System.Type).GetMethod("GetMethod", new Type[] { typeof(string) }));
             * il.Emit(OpCodes.Stloc, classInfoLocal);
             */
            il.Emit(OpCodes.Ldloc, classInfoLocal);
            il.Emit(OpCodes.Ldtoken, typeof(ExceptionAspectAttribute));
            //generator.Emit(OpCodes.Ldloca, )
            il.Emit(OpCodes.Call,
                    typeof(System.Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(System.RuntimeTypeHandle) }));
            il.Emit(OpCodes.Call,
                    typeof(System.Attribute).GetMethod("GetCustomAttribute",
                                                       new Type[] { typeof(System.Reflection.MethodInfo), typeof(System.Type) }));
            il.Emit(OpCodes.Castclass, typeof(ExceptionAspectAttribute));
            il.Emit(OpCodes.Stloc, exAspectLocal);

            il.Emit(OpCodes.Ldloc, exAspectLocal);
            il.Emit(OpCodes.Ldnull);
            il.Emit(OpCodes.Ceq);
            il.Emit(OpCodes.Brtrue_S, castExSuccess);
            il.Emit(OpCodes.Ldloc, exAspectLocal);
            il.Emit(OpCodes.Ldloc, contextLocal);
            il.Emit(OpCodes.Callvirt,
                    typeof(AspectAttribute).GetMethod("Action", new Type[] { typeof(InvokeContext) }));

            il.MarkLabel(castExSuccess);

            #endregion

            #region End Exception Block

            il.EndExceptionBlock();

            #endregion

            if (typeof(void) != returnType)
            {
                il.Emit(OpCodes.Ldloc, resultLocal);
            }

            il.Emit(OpCodes.Ret);
        }