示例#1
0
        private void PatchMethodRef(MethodBody body, Action <TypeReference> onReplace,
                                    MethodReference meth, Instruction instr)
        {
            TypeReference declaringType;
            TypeReference returnType;
            var           methDef      = meth as MethodDefinition ?? meth.TryResolve();
            var           genRef       = meth as GenericInstanceMethod;
            var           methDeclType = meth.DeclaringType.IsGenericInstance
                ? meth.DeclaringType
                : methDef?.DeclaringType ?? meth.DeclaringType;
            var methRetType = meth.ReturnType.IsGenericInstance
                ? meth.ReturnType
                : methDef?.ReturnType ?? meth.ReturnType;

            if (TryGetValue(body.Method, methDeclType, out declaringType))
            {
                onReplace(methDeclType);
            }
            if (TryGetValue(body.Method, methRetType, out returnType))
            {
                onReplace(methRetType);
            }
            TypeReference tempType;
            var           genArgs = new TypeReference[0];

            if (genRef != null && (genArgs = genRef.GenericArguments.Select(
                                       a => TryGetValue(body.Method, a, out tempType) ? tempType : null).ToArray()).Any())
            {
                foreach (var arg in genArgs.Where(a => a != null))
                {
                    onReplace(arg);
                }
            }
            if (returnType == null && declaringType == null && genArgs.All(a => a == null))
            {
                return;
            }
            var newMeth = new MethodReference(meth.Name,
                                              returnType ?? meth.ReturnType,
                                              declaringType ?? meth.DeclaringType)
            {
                CallingConvention = meth.CallingConvention,
                ExplicitThis      = meth.ExplicitThis,
                HasThis           = meth.HasThis
            };

            foreach (var parm in meth.Parameters)
            {
                TypeReference ptype;
                if (TryGetValue(body.Method, parm.ParameterType, out ptype))
                {
                    onReplace(parm.ParameterType);
                }
                var mparm = new ParameterDefinition(parm.Name, parm.Attributes,
                                                    ptype ?? parm.ParameterType);
                newMeth.Parameters.Add(mparm);
            }
            if (genRef == null)
            {
                instr.Operand = newMeth;
                return;
            }
            var genMeth = new GenericInstanceMethod(methDef)
            {
                ReturnType = returnType ?? genRef.ReturnType
            };

            for (var i = 0; i < genRef.GenericArguments.Count; i++)
            {
                var genArg = genArgs[i] ?? genRef.GenericArguments[i];
                genMeth.GenericArguments.Add(genArg);
            }
            instr.Operand = genMeth;
        }