Example #1
0
        private MethodDefinition ImplementInterfaceMethod(TypeDefinition typeDefinition, Type interfaceType, IImplementInterfaceAspect aspect, FieldDefinition aspectField, ImplementationInfo.Method methodImplementationInfo)
        {
            var interfaceMethod    = methodImplementationInfo.InterfaceMethod;
            var aspectMethod       = methodImplementationInfo.AspectMethod;
            var interfaceMethodRef = ModuleDefinition.ImportReference(interfaceMethod);
            var aspectMethodDef    = ModuleDefinition.ImportReference(aspectMethod).Resolve();

            ModuleWeaver.LogInfo($"Implementing method {aspectMethod.Name} in {typeDefinition.FullName}");

            // Creates a new method that will proxy to the "original" method.
            // The interfaces are always explicitly implemented, so that we don't have problems with names collisions
            var newMethodAttrs = Mono.Cecil.MethodAttributes.Private |
                                 Mono.Cecil.MethodAttributes.HideBySig |
                                 Mono.Cecil.MethodAttributes.NewSlot |
                                 Mono.Cecil.MethodAttributes.Virtual |
                                 Mono.Cecil.MethodAttributes.Final;
            var newMethodName       = $"{interfaceType.Namespace}.{interfaceType.Name}.{interfaceMethod.Name}";// GetUniqueMethodName(typeDefinition, aspectMethod.Name);
            var newMethodDefinition = new MethodDefinition(newMethodName, newMethodAttrs, ModuleWeaver.TypeSystem.VoidReference);

            typeDefinition.Methods.Add(newMethodDefinition);
            newMethodDefinition.Overrides.Add(interfaceMethodRef); // This is what makes the implementation "explicit"
            newMethodDefinition.CallingConvention = aspectMethodDef.CallingConvention;
            newMethodDefinition.ExplicitThis      = aspectMethodDef.ExplicitThis;
            newMethodDefinition.HasThis           = aspectMethodDef.HasThis;
            newMethodDefinition.CopyGenericParameters(aspectMethodDef.GenericParameters);
            newMethodDefinition.ReturnType = ResolveTypeReference(aspectMethod.ReturnType, newMethodDefinition.GenericParameters);
            foreach (var parameter in aspectMethod.GetParameters())
            {
                var newParameter = new ParameterDefinition(parameter.Name, ParameterAttributes.None, ResolveTypeReference(parameter.ParameterType, newMethodDefinition.GenericParameters));
                newParameter.IsIn          = parameter.IsIn;
                newParameter.IsLcid        = parameter.IsLcid;
                newParameter.IsOptional    = parameter.IsOptional;
                newParameter.IsOut         = parameter.IsOut;
                newParameter.IsReturnValue = parameter.IsRetval;

                // respect parameters with "params" modifier
                if (parameter.CustomAttributes.Any(attr => attr.AttributeType == typeof(ParamArrayAttribute)))
                {
                    var ctor = typeof(ParamArrayAttribute).GetConstructor(Type.EmptyTypes);
                    var attr = new CustomAttribute(ModuleDefinition.ImportReference(ctor));
                    newParameter.CustomAttributes.Add(attr);
                }

                newMethodDefinition.Parameters.Add(newParameter);
            }

            // Writes the "code" of the new method
            // This will simply retrieve the aspect instance from the private field created in "InitializeAspectsFields"
            // and then call the corresponding method on that instance
            var variableObj = new VariableDefinition(ModuleDefinition.ImportReference(interfaceType));

            newMethodDefinition.Body.InitLocals = true;
            newMethodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg_0));
            newMethodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Ldfld, aspectField));
            newMethodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Castclass, variableObj.VariableType));

            foreach (var p in newMethodDefinition.Parameters)
            {
                newMethodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Ldarg, p));
            }

            if (interfaceMethodRef.HasGenericParameters)
            {
                interfaceMethodRef = interfaceMethodRef.MakeGenericInstanceMethod(newMethodDefinition.GenericParameters.ToArray());
            }

            newMethodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Callvirt, interfaceMethodRef));
            newMethodDefinition.Body.Instructions.Add(Instruction.Create(OpCodes.Ret));

            return(newMethodDefinition);
        }
Example #2
0
        private PropertyDefinition ImplementInterfaceProperty(TypeDefinition typeDefinition, Type interfaceType, IImplementInterfaceAspect aspect, FieldDefinition aspectField, ImplementationInfo.Property propertyImplementationInfo)
        {
            var propertyInfo    = propertyImplementationInfo.PropertyInfo;
            var interfaceGetter = propertyImplementationInfo.InterfaceGetter;
            var interfaceSetter = propertyImplementationInfo.InterfaceSetter;
            var aspectGetter    = propertyImplementationInfo.AspectGetter;
            var aspectSetter    = propertyImplementationInfo.AspectSetter;

            var newPropertyDefinition = new PropertyDefinition(propertyInfo.Name, PropertyAttributes.None, ModuleDefinition.ImportReference(propertyInfo.PropertyType));

            newPropertyDefinition.IsSpecialName        = (propertyInfo.Attributes & System.Reflection.PropertyAttributes.SpecialName) == System.Reflection.PropertyAttributes.SpecialName;
            newPropertyDefinition.IsRuntimeSpecialName = (propertyInfo.Attributes & System.Reflection.PropertyAttributes.RTSpecialName) == System.Reflection.PropertyAttributes.RTSpecialName;
            newPropertyDefinition.HasDefault           = (propertyInfo.Attributes & System.Reflection.PropertyAttributes.HasDefault) == System.Reflection.PropertyAttributes.HasDefault;

            if (aspectGetter != null)
            {
                var getter = ImplementInterfaceMethod(typeDefinition, interfaceType, aspect, aspectField, new ImplementationInfo.Method(interfaceGetter, aspectGetter));
                newPropertyDefinition.GetMethod = getter;
            }

            if (aspectSetter != null)
            {
                var setter = ImplementInterfaceMethod(typeDefinition, interfaceType, aspect, aspectField, new ImplementationInfo.Method(interfaceSetter, aspectSetter));
                newPropertyDefinition.SetMethod = setter;
            }

            typeDefinition.Properties.Add(newPropertyDefinition);
            return(newPropertyDefinition);
        }
Example #3
0
        private void ImplementInterface(TypeDefinition typeDefinition, Type interfaceType, IImplementInterfaceAspect aspect, FieldDefinition aspectField)
        {
            // Ignores the "IImplementInterfaceAspect" interface that serves only as a marker interface
            if (interfaceType == typeof(IImplementInterfaceAspect))
            {
                return;
            }

            // Ignores the "_Attribute" interface that is automatically implemented by all attributes
            if (interfaceType.FullName == "System.Runtime.InteropServices._Attribute")
            {
                return;
            }

            ModuleWeaver.LogInfo($"Implementing interface {interfaceType.FullName} on {typeDefinition.FullName}");

            var implementationInfo = GetImplementationInfo(aspect.GetType(), interfaceType);

            typeDefinition.Interfaces.Add(new InterfaceImplementation(ModuleDefinition.ImportReference(interfaceType)));

            foreach (var item in implementationInfo)
            {
                if (item.Type == ImplementationInfo.Types.Method)
                {
                    ImplementInterfaceMethod(typeDefinition, interfaceType, aspect, aspectField, item as ImplementationInfo.Method);
                }
                else if (item.Type == ImplementationInfo.Types.Property)
                {
                    ImplementInterfaceProperty(typeDefinition, interfaceType, aspect, aspectField, item as ImplementationInfo.Property);
                }
            }
        }