예제 #1
0
        private Instruction AddInterceptCall(ILProcessor ilProcessor, MethodDefinition methDef, MethodDefinition interceptMethDef, CustomAttribute att, Instruction insertBefore)
        {
            var methRef = _assemblyDefinition.MainModule.ImportReference(interceptMethDef);

            ilProcessor.InsertBefore(insertBefore, ilProcessor.CreateLoadInstruction(methDef.Name));

            int methodParamCount = methDef.Parameters.Count;
            int arrayVarNr       = methDef.Body.Variables.Count;

            if (methodParamCount > 0)
            {
                ArrayType objArrType = new ArrayType(_assemblyDefinition.MainModule.TypeSystem.Object);
                methDef.Body.Variables.Add(new VariableDefinition(objArrType));

                methDef.Body.InitLocals = true;

                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldc_I4, methodParamCount));
                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Newarr, _assemblyDefinition.MainModule.TypeSystem.Object));
                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Stloc, arrayVarNr));

                bool pointerToValueTypeVariable;
                TypeSpecification referencedTypeSpec = null;

                for (int i = 0; i < methodParamCount; i++)
                {
                    var paramMetaData = methDef.Parameters[i].ParameterType.MetadataType;
                    if (paramMetaData == MetadataType.UIntPtr || paramMetaData == MetadataType.FunctionPointer ||
                        paramMetaData == MetadataType.IntPtr || paramMetaData == MetadataType.Pointer)
                    {
                        break;
                    }

                    ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldloc, arrayVarNr));
                    ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldc_I4, i));

                    if (methDef.IsStatic)
                    {
                        ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldarg, i));
                    }
                    else
                    {
                        ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldarg, i + 1));
                    }

                    pointerToValueTypeVariable = false;

                    TypeReference paramType = methDef.Parameters[i].ParameterType;
                    if (paramType.IsByReference)
                    {
                        referencedTypeSpec = paramType as TypeSpecification;

                        if (referencedTypeSpec != null)
                        {
                            switch (referencedTypeSpec.ElementType.MetadataType)
                            {
                            case MetadataType.Boolean:
                            case MetadataType.SByte:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_I1));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.Int16:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_I2));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.Int32:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_I4));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.Int64:
                            case MetadataType.UInt64:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_I8));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.Byte:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_U1));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.UInt16:
                            case MetadataType.Char:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_U2));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.UInt32:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_U4));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.Single:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_R4));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.Double:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_R8));
                                pointerToValueTypeVariable = true;
                                break;

                            case MetadataType.IntPtr:
                            case MetadataType.UIntPtr:
                                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_I));
                                pointerToValueTypeVariable = true;
                                break;

                            default:
                                if (referencedTypeSpec.ElementType.IsValueType)
                                {
                                    ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldobj, referencedTypeSpec.ElementType));
                                    pointerToValueTypeVariable = true;
                                }
                                else
                                {
                                    ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldind_Ref));
                                    pointerToValueTypeVariable = false;
                                }
                                break;
                            }
                        }
                        else
                        {
                        }
                    }

                    if (paramType.IsValueType || pointerToValueTypeVariable)
                    {
                        if (pointerToValueTypeVariable)
                        {
                            ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Box, referencedTypeSpec.ElementType));
                        }
                        else
                        {
                            ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Box, paramType));
                        }
                    }
                    ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Stelem_Ref));
                }


                ilProcessor.InsertBefore(insertBefore, ilProcessor.Create(OpCodes.Ldloc, arrayVarNr));
            }
            var ins = ilProcessor.Create(OpCodes.Callvirt, methDef.Module.ImportReference(interceptMethDef));

            ilProcessor.InsertBefore(insertBefore, ins);
            return(ins);
        }