Пример #1
0
        /// <summary>
        /// Create a new method in the declaring type of the given implicit implementation with the given name.
        /// This method will call the implicit implementation.
        /// </summary>
        internal static MethodDefinition CreateExplicitStub(MethodDefinition implicitImpl, string name, MethodDefinition iMethod, bool avoidGenericParam)
        {
            // Create method
            var newMethod = new MethodDefinition(name, implicitImpl.Attributes, implicitImpl.ReturnType);
            newMethod.IsVirtual = false;
            newMethod.IsAbstract = false;
            newMethod.IsFinal = true;

            // Clone generic parameters
            foreach (var gp in implicitImpl.GenericParameters)
            {
                newMethod.GenericParameters.Add(new GenericParameter(gp.Name, newMethod));
            }

            // Update according to new context
            var cloner = new TypeCloner(avoidGenericParam, implicitImpl.Module.TypeSystem);
            newMethod.ReturnType = cloner.Get(implicitImpl.ReturnType, newMethod);

            // Clone parameters
            foreach (var p in iMethod.Parameters)
            {
                newMethod.Parameters.Add(new ParameterDefinition(p.Name, p.Attributes, cloner.Get(p.ParameterType, newMethod)));
            }

            // Add the method
            var targetType = implicitImpl.DeclaringType;
            targetType.Methods.Add(newMethod);


            // Add override
            newMethod.Overrides.Add(iMethod);

            // Create method body
            var body = new MethodBody(newMethod);
            newMethod.Body = body;
            var worker = body.GetILProcessor();

            // Push this 
            worker.Emit(OpCodes.Ldarg, body.ThisParameter);
            for (var i = 0; i < implicitImpl.Parameters.Count; i++)
            {
                var p = iMethod.Parameters[i];
                var newMethodParam = newMethod.Parameters[i];
                worker.Emit(OpCodes.Ldarg, newMethodParam);
                if (/*avoidGenericParam &&*/ p.ParameterType.ContainsGenericParameter)
                {
                    worker.Emit(OpCodes.Box, implicitImpl.Parameters[i].ParameterType);
                }
            }
            worker.Emit(implicitImpl.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, implicitImpl);
            worker.Emit(OpCodes.Ret);

            // Mark method reachable
            if (implicitImpl.IsReachable)
            {
                newMethod.SetReachable(null);
            }

            return newMethod;
        }
Пример #2
0
            /// <summary>
            /// Add a method that has the same signature as basemethod and calls method.
            /// </summary>
            private MethodDefinition AddBridge(MethodDefinition method, MethodDefinition baseMethod)
            {
                var bridge = new MethodDefinition(baseMethod.Name, baseMethod.Attributes, baseMethod.ReturnType)
                {
                    HasThis = true
                };

                var cloner = new TypeCloner(true, method.Module.TypeSystem);

                bridge.ReturnType = cloner.Get(baseMethod.ReturnType, bridge);
                bridge.IsAbstract = false;

                // Clone parameters
                foreach (var p in baseMethod.Parameters)
                {
                    bridge.Parameters.Add(new ParameterDefinition(p.Name, p.Attributes, cloner.Get(p.ParameterType, bridge)));
                }

                // Create body
                var body = new MethodBody(bridge);

                bridge.Body = body;

                // Create code
                var seq = new ILSequence();

                // this
                seq.Emit(OpCodes.Ldarg_0);
                // parameters
                for (var i = 0; i < bridge.Parameters.Count; i++)
                {
                    var p = bridge.Parameters[i];
                    seq.Emit(OpCodes.Ldarg, p);
                    if (baseMethod.Parameters[i].ParameterType.ContainsGenericParameter)
                    {
                        seq.Emit(OpCodes.Unbox, method.Parameters[i].ParameterType);
                    }
                }
                // Call actual method
                seq.Emit(OpCodes.Call, method);
                // Return
                seq.Emit(OpCodes.Ret);

                // Add code to body
                seq.AppendTo(body);
                body.ComputeOffsets();

                // add overrides, so that we can find the method later
                bridge.Overrides.Add(baseMethod);

                // Add to class
                method.DeclaringType.Methods.Add(bridge);
                bridge.SetReachable(reachableContext);

                return(bridge);
            }
            /// <summary>
            /// Add a method that has the same signature as basemethod and calls method.
            /// </summary>
            private MethodDefinition AddBridge(MethodDefinition method, MethodDefinition baseMethod)
            {
                var bridge = new MethodDefinition(baseMethod.Name, baseMethod.Attributes, baseMethod.ReturnType) { HasThis = true };

                var cloner = new TypeCloner(true, method.Module.TypeSystem);
                bridge.ReturnType = cloner.Get(baseMethod.ReturnType, bridge);
                bridge.IsAbstract = false;

                // Clone parameters
                foreach (var p in baseMethod.Parameters)
                {
                    bridge.Parameters.Add(new ParameterDefinition(p.Name, p.Attributes, cloner.Get(p.ParameterType, bridge)));
                }

                // Create body
                var body = new MethodBody(bridge);
                bridge.Body = body;

                // Create code
                var seq = new ILSequence();
                // this
                seq.Emit(OpCodes.Ldarg_0);
                // parameters
                for (var i = 0; i < bridge.Parameters.Count; i++)
                {
                    var p = bridge.Parameters[i];
                    seq.Emit(OpCodes.Ldarg, p);
                    if (baseMethod.Parameters[i].ParameterType.ContainsGenericParameter)
                    {
                        seq.Emit(OpCodes.Unbox, method.Parameters[i].ParameterType);
                    }
                }
                // Call actual method
                seq.Emit(OpCodes.Call, method);
                // Return
                seq.Emit(OpCodes.Ret);

                // Add code to body
                seq.AppendTo(body);
                body.ComputeOffsets();

                // add overrides, so that we can find the method later
                bridge.Overrides.Add(baseMethod);

                // Add to class
                method.DeclaringType.Methods.Add(bridge);
                bridge.SetReachable(reachableContext);

                return bridge;
            }
Пример #4
0
        /// <summary>
        /// Create a new method in the declaring type of the given implicit implementation with the given name.
        /// This method will call the implicit implementation.
        /// </summary>
        internal static MethodDefinition CreateExplicitStub(MethodDefinition implicitImpl, string name, MethodDefinition iMethod, bool avoidGenericParam)
        {
            // Create method
            var newMethod = new MethodDefinition(name, implicitImpl.Attributes, implicitImpl.ReturnType);

            newMethod.IsVirtual  = false;
            newMethod.IsAbstract = false;
            newMethod.IsFinal    = true;

            // Clone generic parameters
            foreach (var gp in implicitImpl.GenericParameters)
            {
                newMethod.GenericParameters.Add(new GenericParameter(gp.Name, newMethod));
            }

            // Update according to new context
            var cloner = new TypeCloner(avoidGenericParam, implicitImpl.Module.TypeSystem);

            newMethod.ReturnType = cloner.Get(implicitImpl.ReturnType, newMethod);

            // Clone parameters
            foreach (var p in iMethod.Parameters)
            {
                newMethod.Parameters.Add(new ParameterDefinition(p.Name, p.Attributes, cloner.Get(p.ParameterType, newMethod)));
            }

            // Add the method
            var targetType = implicitImpl.DeclaringType;

            targetType.Methods.Add(newMethod);


            // Add override
            newMethod.Overrides.Add(iMethod);

            // Create method body
            var body = new MethodBody(newMethod);

            newMethod.Body = body;
            var worker = body.GetILProcessor();

            // Push this
            worker.Emit(OpCodes.Ldarg, body.ThisParameter);
            for (var i = 0; i < implicitImpl.Parameters.Count; i++)
            {
                var p = iMethod.Parameters[i];
                var newMethodParam = newMethod.Parameters[i];
                worker.Emit(OpCodes.Ldarg, newMethodParam);
                if (/*avoidGenericParam &&*/ p.ParameterType.ContainsGenericParameter)
                {
                    worker.Emit(OpCodes.Box, implicitImpl.Parameters[i].ParameterType);
                }
            }
            worker.Emit(implicitImpl.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, implicitImpl);
            worker.Emit(OpCodes.Ret);

            // Mark method reachable
            if (implicitImpl.IsReachable)
            {
                newMethod.SetReachable(null);
            }

            return(newMethod);
        }