Inheritance: MemberActionAttribute
Beispiel #1
0
        /// <summary>
        ///     Creates a new property in the target assembly, but doesn't set its accessors.
        /// </summary>
        /// <param name="targetType">Type of the target.</param>
        /// <param name="yourProperty">Your property.</param>
        /// <param name="newPropAttr">The new property attribute.</param>
        /// <exception cref="PatchDeclerationException">Thrown if this member collides with another member, and the error cannot be resolved.</exception>
        private NewMemberStatus CreateNewProperty(TypeDefinition targetType, PropertyDefinition yourProperty,
                                                  NewMemberAttribute newPropAttr)
        {
            if (newPropAttr.IsImplicit)
            {
                Log_implicitly_creating_member("property", yourProperty);
            }
            else
            {
                Log_creating_member("property", yourProperty);
            }
            var maybeDuplicate = targetType.GetProperty(yourProperty.Name,
                                                        yourProperty.Parameters.Select(x => x.ParameterType));

            if (maybeDuplicate != null)
            {
                Log_duplicate_member("property", yourProperty, maybeDuplicate);
                if ((DebugOptions & DebugFlags.CreationOverwrites) != 0)
                {
                    Log_overwriting();
                    return(NewMemberStatus.Continue);
                }
                if (newPropAttr.IsImplicit)
                {
                    return(NewMemberStatus.InvalidItem);
                }
                throw Errors.Duplicate_member("property", yourProperty.FullName, maybeDuplicate.FullName);
            }
            var targetPropertyType = FixTypeReference(yourProperty.PropertyType);
            var targetProperty     = new PropertyDefinition(yourProperty.Name,
                                                            yourProperty.Attributes,
                                                            targetPropertyType)
            {
                HasThis    = yourProperty.HasThis,
                Constant   = yourProperty.Constant,
                HasDefault = yourProperty.HasDefault
            };

            targetType.Properties.Add(targetProperty);
            foreach (var param in yourProperty.Parameters)
            {
                targetProperty.Parameters.Add(new ParameterDefinition(param.Name, param.Attributes,
                                                                      FixTypeReference(param.ParameterType)));
            }
            return(NewMemberStatus.Continue);
        }
Beispiel #2
0
        /// <summary>
        /// Creates a new field in the target assembly, for the specified type.
        /// </summary>
        /// <param name="targetDeclaringType">The target declaring type.</param>
        /// <param name="yourField">Your field.</param>
        /// <param name="attr">The action attribute.</param>
        /// <exception cref="PatchDeclerationException">Thrown if this member collides with another member, and the error cannot be resolved.</exception>
        /// <returns></returns>
        private NewMemberStatus CreateNewField(TypeDefinition targetDeclaringType, FieldDefinition yourField,
                                               NewMemberAttribute attr)
        {
            if (attr.IsImplicit)
            {
                Log_implicitly_creating_member("field", yourField);
            }
            else
            {
                Log_creating_member("field", yourField);
            }
            var maybeDuplicate = targetDeclaringType.GetField(yourField.Name);

            if (maybeDuplicate != null)
            {
                Log_duplicate_member("field", yourField, maybeDuplicate);
                if ((DebugOptions & DebugFlags.CreationOverwrites) != 0)
                {
                    Log_overwriting();
                    return(NewMemberStatus.Continue);
                }
                if (attr.IsImplicit)
                {
                    return(NewMemberStatus.InvalidItem);
                }
                throw Errors.Duplicate_member("type", yourField.FullName, maybeDuplicate.FullName);
            }
            var targetField =
                new FieldDefinition(yourField.Name, yourField.Resolve().Attributes, FixTypeReference(yourField.FieldType))
            {
                InitialValue = yourField.InitialValue,                         //probably for string consts
                Constant     = yourField.Constant
            };

            targetDeclaringType.Fields.Add(targetField);
            return(NewMemberStatus.Continue);
        }
Beispiel #3
0
        /// <summary>
        /// Creates a new method in the target assembly, for the specified type.
        /// </summary>
        /// <param name="targetDeclaringType">The type declaring the method in the target assembly.</param>
        /// <param name="yourMethod">Your method, which describes the method to create..</param>
        /// <param name="actionAttribute">The action attribute ordering creation.</param>
        /// <returns></returns>
        /// <exception cref="PatchDeclerationException">Thrown if this member collides with another member, and the error cannot be resolved.</exception>
        private NewMemberStatus CreateNewMethod(TypeDefinition targetDeclaringType, MethodDefinition yourMethod,
                                                NewMemberAttribute actionAttribute)
        {
            if (actionAttribute.IsImplicit)
            {
                Log_implicitly_creating_member("method", yourMethod);
            }
            else
            {
                Log_creating_member("method", yourMethod);
            }

            var maybeDuplicate = targetDeclaringType.GetMethodsLike(yourMethod).FirstOrDefault();

            if (maybeDuplicate != null)
            {
                Log_duplicate_member("method", yourMethod, maybeDuplicate);
                if ((DebugOptions & DebugFlags.CreationOverwrites) != 0)
                {
                    Log_overwriting();
                    //this only okay for controlled testing code.
                    return(NewMemberStatus.Continue);
                }
                if (actionAttribute.IsImplicit)
                {
                    return(NewMemberStatus.InvalidItem);
                }
                throw Errors.Duplicate_member("type", yourMethod.FullName, maybeDuplicate.FullName);
            }

            var targetMethod = new MethodDefinition(yourMethod.Name, yourMethod.Attributes,
                                                    yourMethod.ReturnType)
            {
                ImplAttributes      = yourMethod.ImplAttributes,
                SemanticsAttributes = yourMethod.SemanticsAttributes,
                CallingConvention   = yourMethod.CallingConvention,
                //all the Attributes and Conventions take care of most of the IsX/HasY properties, except for a few.
                //this can be seen by looking at the Cecil code, where you can see which fields MethodDefinition has.
                HasThis        = yourMethod.HasThis,
                ExplicitThis   = yourMethod.ExplicitThis,
                NoInlining     = yourMethod.NoInlining,
                NoOptimization = yourMethod.NoOptimization,
                ReturnType     = yourMethod.ReturnType                     //<---- this is temporary (setting it again to emphasize)
            };

            targetMethod.SecurityDeclarations.AddRange(yourMethod.SecurityDeclarations.Select(x => new SecurityDeclaration(x.Action, x.GetBlob())));

            targetDeclaringType.Methods.Add(targetMethod);

            //First we add the parameters to the method so its signature is correct.
            //Note that we do not fix the types at this stage.
            //This is because FixType calls can end up looking for the method we're adding right now
            //if any of the parameter types are MVars. The signature has to be similar to yourMethod's signature
            //if FixType is to find this definition.
            //this may seem needlessly complicated and rather risky, and I thought so too, but there really isn't any way around it
            //or at least, I'm not clever enough to come up with one that doesn't introduce more problems
            //(believe me, I've tried all sorts of things)
            foreach (var yourParam in yourMethod.Parameters)
            {
                targetMethod.Parameters.Add(new ParameterDefinition(yourParam.ParameterType));
            }

            //Note we're not adding any constraints yet because doing that involves FixType calls
            //also, the T : S constraint involves 2 MVars, so unless we add all the MVars first, FixType calls could never be resolved.

            var genList = new List <GenericParameter>();

            foreach (var yourTypeParam in yourMethod.GenericParameters)
            {
                var targetTypeParam = new GenericParameter(yourTypeParam.Name, targetMethod)
                {
                    Attributes = yourTypeParam.Attributes                     //includes non-type constraints
                };
                genList.Add(targetTypeParam);
            }

            targetMethod.GenericParameters.AddRange(genList);
            //NOW we're adding constraints, when the signature is stable and when all MVars have been declared.
            for (int i = 0; i < targetMethod.GenericParameters.Count; i++)
            {
                foreach (var constraint in yourMethod.GenericParameters[i].Constraints)
                {
                    targetMethod.GenericParameters[i].Constraints.Add(FixTypeReference(constraint));
                }
            }

            // note that we don't add the parameters to the method directly, at least not at first.
            //this is because we're making FixType calls, and again, they can end up looking up targetMethod
            //changing the signature will just end up with FixType not finding it.
            var parList = new List <ParameterDefinition>();

            foreach (var yourParam in yourMethod.Parameters)
            {
                var targetParamType = FixTypeReference(yourParam.ParameterType);
                var targetParam     = new ParameterDefinition(yourParam.Name, yourParam.Attributes, targetParamType)
                {
                    Constant = yourParam.Constant,
                };
                parList.Add(targetParam);
            }
            //we reset the parameters after we're done with that in as near an atomic operation as possible, and without any FixType calls.
            targetMethod.Parameters.Clear();
            targetMethod.Parameters.AddRange(parList);

            //we also fix this guy:
            targetMethod.ReturnType = FixTypeReference(yourMethod.ReturnType);

            //note that YOU DO NOT do targetMethod.Parameters.AddRangE(yourMethod.Parameters)
            //ParameterDefinitions are mutable!  and doing this can mutate them...
            return(NewMemberStatus.Continue);
        }