Beispiel #1
0
        private void CollectInterface(MethodSlotList slots, IType interfaceType)
        {
            var type = slots.Type;

            // Methods
            foreach (var interfaceBuildMethod in interfaceType.Methods)
            {
                var targetSlotMethod = slots.GetMethod(interfaceBuildMethod, true);

                if (targetSlotMethod.Depth == 0)
                {
                    // Root type overrides interface.
                    var targetBuildMethod    = targetSlotMethod.Method;
                    var targetMethodState    = _state.GetMethod(targetBuildMethod);
                    var interfaceMethodState = _state.GetMethod(interfaceBuildMethod);

                    if (NeedsInterfaceOverride(interfaceMethodState, targetMethodState))
                    {
                        targetMethodState.Overrides.Add(interfaceBuildMethod);
                    }
                }
                else
                {
                    // Base type overrides interface.
                    var typeState = _state.GetType(type);

                    var targetBuildMethod = targetSlotMethod.Method;

                    // If not overriden by root type, build proxy method and call base method.
                    if (typeState.Overrides.Contains(interfaceBuildMethod))
                    {
                        continue;
                    }

                    // If base method could not be called from this type, skip proxy method.
                    // If assembly is valid base method is always callable.
                    if (!CanCallMethod(type, targetBuildMethod))
                    {
                        continue;
                    }

                    // Add proxy method.
                    var proxy =
                        new ProxyBuildMethod()
                    {
                        OverridenMethod = interfaceBuildMethod,
                        CalledMethod    = targetBuildMethod,
                    };

                    typeState.ProxyMethods.Add(proxy);
                    typeState.Overrides.Add(interfaceBuildMethod);
                }
            }

            // Children
            foreach (var childInterfaceType in interfaceType.Interfaces)
            {
                CollectInterface(slots, childInterfaceType);
            }
        }
Beispiel #2
0
        private void ChangeProxyMethod(BuildType type, ProxyBuildMethod proxyMethod)
        {
            var overridenMethod = proxyMethod.OverridenMethod;
            var calledMethod    = proxyMethod.CalledMethod;

            var method = type.Methods.Add();

            method.Name        = _nameGenerator.GenerateUniqueString();
            method.Visibility  = MethodVisibilityFlags.Private;
            method.HasThis     = true;
            method.IsHideBySig = true;
            method.IsVirtual   = true;
            method.IsNewSlot   = true;
            method.IsFinal     = true;
            method.CallConv    = overridenMethod.CallConv;

            // Return type
            {
                var returnType = method.ReturnType;
                returnType.Type = overridenMethod.ReturnType.ToSignature(type.Module);
            }

            // Parameters
            foreach (var overridenMethodParameter in overridenMethod.Parameters)
            {
                var parameter = method.Parameters.Add();
                parameter.Name       = overridenMethodParameter.Name;
                parameter.IsIn       = overridenMethodParameter.IsIn;
                parameter.IsOut      = overridenMethodParameter.IsOut;
                parameter.IsOptional = overridenMethodParameter.IsOptional;
                parameter.IsLcid     = overridenMethodParameter.IsLcid;
                parameter.Type       = overridenMethodParameter.Type.ToSignature(type.Module);
            }

            // GenericParameters
            foreach (var interfaceGenericParameter in overridenMethod.GenericParameters)
            {
                var genericParameter = method.GenericParameters.Add();
                genericParameter.Name     = interfaceGenericParameter.Name;
                genericParameter.Variance = interfaceGenericParameter.Variance;
                genericParameter.DefaultConstructorConstraint = interfaceGenericParameter.DefaultConstructorConstraint;
                genericParameter.ReferenceTypeConstraint      = interfaceGenericParameter.ReferenceTypeConstraint;
                genericParameter.ValueTypeConstraint          = interfaceGenericParameter.ValueTypeConstraint;

                // Constraints
                foreach (var constraintType in interfaceGenericParameter.Constraints)
                {
                    genericParameter.Constraints.Add(constraintType.ToSignature(type.Module));
                }
            }

            // Body
            {
                var methodBody = new MethodBody();

                // Instructions
                var instructions = methodBody.Instructions;

                methodBody.MaxStackSize = method.Parameters.Count + 2;                 // this + parameters + return

                // Load this
                instructions.Add(Instruction.GetLdarg(0));

                // Load parameters
                for (int i = 0; i < method.Parameters.Count; i++)
                {
                    instructions.Add(Instruction.GetLdarg(i + 1));
                }

                var calledMethodSig = calledMethod.ToSignature(type.Module);
                if (calledMethod.GenericParameters.Count > 0)
                {
                    var genericArguments = new TypeSignature[calledMethod.GenericParameters.Count];
                    for (int i = 0; i < genericArguments.Length; i++)
                    {
                        genericArguments[i] = new GenericParameterType(true, i);
                    }

                    calledMethodSig = new GenericMethodReference((MethodReference)calledMethodSig, genericArguments);
                }

                // Call method
                instructions.Add(new Instruction(
                                     calledMethod.IsVirtual ? OpCodes.Callvirt : OpCodes.Call,
                                     calledMethodSig));

                instructions.Add(new Instruction(OpCodes.Ret));

                methodBody.Build(method);
            }

            // Add override.
            method.Overrides.Add(overridenMethod.ToReference(type.Module));
        }