コード例 #1
0
        private static void EncapsulateMethod(AssemblyDefinition assembly, ModuleDefinition module,
                                              TypeDefinition type, MethodDefinition method, string overrideName = null, string overrideMethod =
                                              nameof(AOPProcessor.OnMethod))
        {
            // New body for current method (capsule)
            var newMethodBody = new List <Instruction>();

            newMethodBody.Add(Instruction.Create(method.IsStatic ? OpCodes.Ldnull : OpCodes.Ldarg_0)); // ldnull / ldarg_0
            newMethodBody.Add(Instruction.Create(OpCodes.Ldtoken, type));
            newMethodBody.Add(Instruction.Create(OpCodes.Call, typeof(Type).GetMonoMethod(module, nameof(Type.GetTypeFromHandle))));

            var mName = method.Name;

            if (!string.IsNullOrEmpty(overrideName))
            {
                mName = overrideName;
            }

            newMethodBody.Add(Instruction.Create(OpCodes.Ldstr, mName));
            newMethodBody.Add(Instruction.Create(OpCodes.Ldc_I4, method.Parameters.Count));
            newMethodBody.Add(Instruction.Create(OpCodes.Newarr, module.ImportReference(typeof(object))));

            for (var num = 0; num < method.Parameters.Count; num++)
            {
                var param = method.Parameters[num];
                var pType = param.ParameterType;

                newMethodBody.Add(Instruction.Create(OpCodes.Dup));
                newMethodBody.Add(Instruction.Create(OpCodes.Ldc_I4, num));
                newMethodBody.Add(Instruction.Create(OpCodes.Ldarg, param));
                if (param.ParameterType.IsValueType || param.ParameterType.IsGenericParameter)
                {
                    newMethodBody.Add(Instruction.Create(OpCodes.Box, pType));
                }
                newMethodBody.Add(Instruction.Create(OpCodes.Stelem_Ref));
            }


            if (module.HasType(typeof(AOPProcessor)))
            {
                newMethodBody.Add(Instruction.Create(OpCodes.Call,
                                                     module.GetType(typeof(AOPProcessor))
                                                     .GetMethod(overrideMethod)));
            }
            else
            {
                newMethodBody.Add(Instruction.Create(OpCodes.Call, typeof(AOPProcessor).GetMonoMethod(module,
                                                                                                      overrideMethod)));
            }

            if (method.ReturnType.FullName != typeof(void).FullName)
            {
                if (method.ReturnType.IsValueType)
                {
                    newMethodBody.Add(Instruction.Create(OpCodes.Unbox_Any, method.ReturnType));
                }
            }
            else
            {
                newMethodBody.Add(Instruction.Create(OpCodes.Pop));
            }

            newMethodBody.Add(Instruction.Create(OpCodes.Ret));

            // Create new method
            var internalMethod = new MethodDefinition(method.Name + AOPProcessor.APPENDIX, method.Attributes, method.ReturnType);

            foreach (var param in method.Parameters)
            {
                var newParam = new ParameterDefinition(param.Name, param.Attributes, param.ParameterType);
                newParam.HasDefault = false;
                newParam.IsOptional = false;
                internalMethod.Parameters
                .Add(newParam);
            }

            // Copy generic parameters
            foreach (var genericParameter in method.GenericParameters)
            {
                internalMethod.GenericParameters
                .Add(new GenericParameter(genericParameter.Name, internalMethod));
            }

            var bodyClone = new MethodBody(method);

            bodyClone.AppendInstructions(newMethodBody);
            bodyClone.MaxStackSize = 8;

            // Replace method bodies
            internalMethod.Body = method.Body;
            method.Body         = bodyClone;
            type.Methods.Add(internalMethod);
        }