示例#1
0
        static void AddCollectionEquals(TypeDefinition type, MethodDefinition collectionEquals, PropertyDefinition property, TypeDefinition propType, Collection <Instruction> e, ParameterDefinition left, ParameterDefinition right)
        {
            e.If(
                cf =>
            {
                cf.Add(Instruction.Create(type.GetLdArgForType(), right));
                cf.Add(Instruction.Create(OpCodes.Ldnull));
                cf.Add(Instruction.Create(OpCodes.Ceq));
            },
                t => t.Add(Instruction.Create(OpCodes.Ldc_I4_0)),
                es =>
            {
                var getMethod         = property.GetGetMethod(type);
                var getMethodImported = ReferenceFinder.ImportCustom(getMethod);

                es.Add(Instruction.Create(type.GetLdArgForType(), left));
                es.Add(Instruction.Create(getMethodImported.GetCallForMethod(), getMethodImported));
                if (propType.IsValueType && !property.PropertyType.IsArray)
                {
                    es.Add(Instruction.Create(OpCodes.Box, propType));
                }

                es.Add(Instruction.Create(type.GetLdArgForType(), right));
                es.Add(Instruction.Create(getMethodImported.GetCallForMethod(), getMethodImported));
                if (propType.IsValueType && !property.PropertyType.IsArray)
                {
                    es.Add(Instruction.Create(OpCodes.Box, propType));
                }

                es.Add(Instruction.Create(OpCodes.Call, collectionEquals));
            });
        }
示例#2
0
        static VariableDefinition AddNullableProperty(PropertyDefinition property, Collection <Instruction> ins, TypeDefinition type, VariableDefinition variable)
        {
            ins.If(c =>
            {
                var nullablePropertyResolved = property.PropertyType.Resolve();
                var nullablePropertyImported = ReferenceFinder.ImportCustom(property.PropertyType);

                ins.Add(Instruction.Create(OpCodes.Ldarg_0));
                var getMethod = ReferenceFinder.ImportCustom(property.GetGetMethod(type));
                c.Add(Instruction.Create(OpCodes.Call, getMethod));

                variable = new VariableDefinition(getMethod.ReturnType);
                c.Add(Instruction.Create(OpCodes.Stloc, variable));
                c.Add(Instruction.Create(OpCodes.Ldloca, variable));

                var hasValuePropertyResolved = nullablePropertyResolved.Properties.First(x => x.Name == "HasValue").Resolve();
                var hasMethod = ReferenceFinder.ImportCustom(hasValuePropertyResolved.GetGetMethod(nullablePropertyImported));
                c.Add(Instruction.Create(OpCodes.Call, hasMethod));
            },
                   t =>
            {
                var nullableProperty = ReferenceFinder.ImportCustom(property.PropertyType);

                t.Add(Instruction.Create(OpCodes.Ldarg_0));
                var imp  = property.GetGetMethod(type);
                var imp2 = ReferenceFinder.ImportCustom(imp);

                t.Add(Instruction.Create(OpCodes.Call, imp2));
                t.Add(Instruction.Create(OpCodes.Box, nullableProperty));
                t.Add(Instruction.Create(OpCodes.Callvirt, ReferenceFinder.Object.GetHashcode));
            },
                   e => e.Add(Instruction.Create(OpCodes.Ldc_I4_0)));
            return(variable);
        }
示例#3
0
        static void LoadVariable(PropertyDefinition property, Collection <Instruction> ins, TypeDefinition type)
        {
            var get      = property.GetGetMethod(type);
            var imported = ReferenceFinder.ImportCustom(get);

            ins.Add(Instruction.Create(OpCodes.Ldarg_0));
            ins.Add(Instruction.Create(OpCodes.Call, imported));
        }
示例#4
0
        static void AddCustomLogicCall(TypeDefinition type, MethodBody body, Collection <Instruction> ins, MethodDefinition[] customLogic)
        {
            ins.IfNot(
                c =>
            {
                var customMethod = ReferenceFinder.ImportCustom(customLogic[0]);

                var parameters = customMethod.Parameters;
                if (parameters.Count != 1)
                {
                    throw new WeavingException(
                        string.Format("Custom equals of type {0} have to have one parameter.", type.FullName));
                }
                if (parameters[0].ParameterType.Resolve().FullName != type.FullName)
                {
                    throw new WeavingException(
                        string.Format("Custom equals of type {0} have to have one parameter of type {0}.", type.FullName));
                }

                MethodReference selectedMethod;
                TypeReference resolverType;
                if (customMethod.DeclaringType.HasGenericParameters)
                {
                    var genericInstanceType = type.GetGenericInstanceType(type);
                    resolverType            = ReferenceFinder.ImportCustom(genericInstanceType);
                    var newRef = new MethodReference(customMethod.Name, customMethod.ReturnType)
                    {
                        DeclaringType = resolverType,
                        HasThis       = true,
                    };
                    newRef.Parameters.Add(customMethod.Parameters[0].Name, resolverType);

                    selectedMethod = newRef;
                }
                else
                {
                    resolverType   = type;
                    selectedMethod = customMethod;
                }

                var imported = ReferenceFinder.ImportCustom(selectedMethod);
                if (!type.IsValueType)
                {
                    ins.Add(Instruction.Create(OpCodes.Ldarg_0));
                }
                else
                {
                    var argVariable = body.Variables.Add("argVariable", resolverType);
                    ins.Add(Instruction.Create(OpCodes.Ldarg_0));
                    ins.Add(Instruction.Create(OpCodes.Stloc, argVariable));

                    ins.Add(Instruction.Create(OpCodes.Ldloca, argVariable));
                }
                ins.Add(Instruction.Create(OpCodes.Ldarg_1));
                ins.Add(Instruction.Create(imported.GetCallForMethod(), imported));
            },
                AddReturnFalse);
        }
示例#5
0
        static VariableDefinition AddPropertyCode(PropertyDefinition property, bool isFirst, Collection <Instruction> ins, VariableDefinition resultVariable, MethodDefinition method, TypeDefinition type)
        {
            VariableDefinition variable = null;
            bool isCollection;
            var  propType = ReferenceFinder.ImportCustom(property.PropertyType.GetGenericInstanceType(type));

            if (property.PropertyType.IsGenericParameter)
            {
                isCollection = false;
            }
            else
            {
                isCollection = propType.Resolve().IsCollection() || property.PropertyType.IsArray;
            }

            AddMultiplicityByMagicNumber(isFirst, ins, resultVariable, isCollection);

            if (property.PropertyType.FullName.StartsWith("System.Nullable`1"))
            {
                variable = AddNullableProperty(property, ins, type, variable);
            }
            else if (property.PropertyType.IsValueType || property.PropertyType.IsGenericParameter)
            {
                LoadVariable(property, ins, type);
                if (property.PropertyType.FullName != "System.Int32")
                {
                    ins.Add(Instruction.Create(OpCodes.Box, propType));
                    ins.Add(Instruction.Create(OpCodes.Callvirt, ReferenceFinder.Object.GetHashcode));
                }
            }
            else
            {
                if (isCollection)
                {
                    AddCollectionCode(property, isFirst, ins, resultVariable, method, type);
                }
                else
                {
                    LoadVariable(property, ins, type);
                    AddNormalCode(property, ins, type);
                }
            }

            if (!isFirst && !isCollection)
            {
                ins.Add(Instruction.Create(OpCodes.Xor));
            }

            if (!isCollection)
            {
                ins.Add(Instruction.Create(OpCodes.Stloc, resultVariable));
            }

            return(variable);
        }
示例#6
0
        static void GetEnumerator(Collection <Instruction> ins, VariableDefinition variable, PropertyDefinition property)
        {
            if (property.PropertyType.IsValueType)
            {
                var imported = ReferenceFinder.ImportCustom(property.PropertyType);
                ins.Add(Instruction.Create(OpCodes.Box, imported));
            }

            ins.Add(Instruction.Create(OpCodes.Callvirt, ReferenceFinder.IEnumerable.GetEnumerator));
            ins.Add(Instruction.Create(OpCodes.Stloc, variable));
        }
示例#7
0
        static void AddSimpleValueCheck(Collection <Instruction> c, PropertyDefinition property, TypeDefinition type, ParameterDefinition left, ParameterDefinition right)
        {
            var getMethod         = property.GetGetMethod(type);
            var getMethodImported = ReferenceFinder.ImportCustom(getMethod);

            c.Add(Instruction.Create(type.GetLdArgForType(), left));
            c.Add(Instruction.Create(getMethodImported.GetCallForMethod(), getMethodImported));

            c.Add(Instruction.Create(type.GetLdArgForType(), right));
            c.Add(Instruction.Create(getMethodImported.GetCallForMethod(), getMethodImported));

            c.Add(Instruction.Create(OpCodes.Ceq));
        }
示例#8
0
        public static MethodDefinition Inject(TypeDefinition type, bool ignoreBaseClassProperties)
        {
            var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
            var method           = new MethodDefinition("GetHashCode", methodAttributes, ReferenceFinder.Int32.TypeReference);

            method.CustomAttributes.MarkAsGeneratedCode();

            var resultVariable = method.Body.Variables.Add("result", ReferenceFinder.Int32.TypeReference);

            var body = method.Body;

            body.InitLocals = true;
            var ins = body.Instructions;

            ins.Add(Instruction.Create(OpCodes.Ldc_I4_0));
            ins.Add(Instruction.Create(OpCodes.Stloc, resultVariable));

            var properties = ReferenceFinder.ImportCustom(type).Resolve().GetPropertiesWithoutIgnores(ignoreAttributeName);

            if (ignoreBaseClassProperties)
            {
                properties = properties.IgnoreBaseClassProperties(type);
            }

            if (properties.Length == 0)
            {
                AddResultInit(ins, resultVariable);
            }

            var isFirst = true;

            foreach (var property in properties)
            {
                var variable = AddPropertyCode(property, isFirst, ins, resultVariable, method, type);

                if (variable != null)
                {
                    method.Body.Variables.Add(variable);
                }

                isFirst = false;
            }

            AddReturnCode(ins, resultVariable);

            body.OptimizeMacros();

            type.Methods.AddOrReplace(method);

            return(method);
        }
示例#9
0
        public static MethodReference GetGetMethod(this PropertyDefinition property, TypeReference targetType)
        {
            MethodReference method = property.GetMethod;

            if (method.DeclaringType.HasGenericParameters)
            {
                var genericInstanceType = property.DeclaringType.GetGenericInstanceType(targetType);
                method = new MethodReference(method.Name, method.ReturnType.IsGenericParameter ? method.ReturnType : ReferenceFinder.ImportCustom(method.ReturnType))
                {
                    DeclaringType = ReferenceFinder.ImportCustom(genericInstanceType),
                    HasThis       = true
                };
            }
            return(method);
        }
示例#10
0
        static void AddNormalCheck(TypeDefinition type, Collection <Instruction> c, PropertyDefinition property, ParameterDefinition left, ParameterDefinition right)
        {
            var genericInstance   = new Lazy <TypeReference>(() => ReferenceFinder.ImportCustom(property.PropertyType.GetGenericInstanceType(type)));
            var getMethodImported = ReferenceFinder.ImportCustom(property.GetGetMethod(type));

            c.Add(Instruction.Create(type.GetLdArgForType(), left));
            c.Add(Instruction.Create(getMethodImported.GetCallForMethod(), getMethodImported));
            if (property.PropertyType.IsValueType || property.PropertyType.IsGenericParameter)
            {
                c.Add(Instruction.Create(OpCodes.Box, genericInstance.Value));
            }
            c.Add(Instruction.Create(type.GetLdArgForType(), right));
            c.Add(Instruction.Create(getMethodImported.GetCallForMethod(), getMethodImported));
            if (property.PropertyType.IsValueType || property.PropertyType.IsGenericParameter)
            {
                c.Add(Instruction.Create(OpCodes.Box, genericInstance.Value));
            }
            c.Add(Instruction.Create(OpCodes.Call, ReferenceFinder.Object.StaticEquals));
        }
示例#11
0
        static void AddCustomLogicCall(TypeDefinition type, MethodBody body, Collection <Instruction> ins, MethodDefinition customLogic)
        {
            var customMethod = ReferenceFinder.ImportCustom(customLogic);

            var parameters = customMethod.Parameters;

            if (parameters.Count != 0)
            {
                throw new WeavingException(
                          string.Format("Custom GetHashCode of type {0} have to have empty parameter list.", type.FullName));
            }
            if (customMethod.ReturnType.FullName != typeof(int).FullName)
            {
                throw new WeavingException(
                          string.Format("Custom GetHashCode of type {0} have to return int.", type.FullName));
            }

            MethodReference selectedMethod;
            TypeReference   resolverType;

            if (customMethod.DeclaringType.HasGenericParameters)
            {
                var genericInstanceType = type.GetGenericInstanceType(type);
                resolverType = ReferenceFinder.ImportCustom(genericInstanceType);
                var newRef = new MethodReference(customMethod.Name, customMethod.ReturnType)
                {
                    DeclaringType = resolverType,
                    HasThis       = true,
                };

                selectedMethod = newRef;
            }
            else
            {
                selectedMethod = customMethod;
            }

            var imported = ReferenceFinder.ImportCustom(selectedMethod);

            ins.Add(Instruction.Create(OpCodes.Ldarg_0));
            ins.Add(Instruction.Create(imported.GetCallForMethod(), imported));
        }
示例#12
0
        public static MethodDefinition Inject(TypeDefinition type, bool ignoreBaseClassProperties)
        {
            var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual;
            var method           = new MethodDefinition("GetHashCode", methodAttributes, ReferenceFinder.Int32.TypeReference);

            method.CustomAttributes.MarkAsGeneratedCode();

            var resultVariable = method.Body.Variables.Add("result", ReferenceFinder.Int32.TypeReference);

            var body = method.Body;

            body.InitLocals = true;
            var ins = body.Instructions;

            ins.Add(Instruction.Create(OpCodes.Ldc_I4_0));
            ins.Add(Instruction.Create(OpCodes.Stloc, resultVariable));

            var properties = ReferenceFinder.ImportCustom(type).Resolve().GetPropertiesWithoutIgnores(ignoreAttributeName);

            if (ignoreBaseClassProperties)
            {
                properties = properties.IgnoreBaseClassProperties(type);
            }

            if (properties.Length == 0)
            {
                AddResultInit(ins, resultVariable);
            }


            var methods     = type.GetMethods();
            var customLogic = methods
                              .Where(x => x.CustomAttributes.Any(y => y.AttributeType.Name == customAttribute)).ToArray();

            if (customLogic.Length > 2)
            {
                throw new WeavingException("Only one custom method can be specified.");
            }

            var isFirst = true;

            foreach (var property in properties)
            {
                var variable = AddPropertyCode(property, isFirst, ins, resultVariable, method, type);

                if (variable != null)
                {
                    method.Body.Variables.Add(variable);
                }

                isFirst = false;
            }

            if (customLogic.Length == 1)
            {
                ins.Add(Instruction.Create(OpCodes.Ldloc, resultVariable));
                ins.Add(Instruction.Create(OpCodes.Ldc_I4, magicNumber));
                ins.Add(Instruction.Create(OpCodes.Mul));
                AddCustomLogicCall(type, body, ins, customLogic[0]);
                ins.Add(Instruction.Create(OpCodes.Xor));
                ins.Add(Instruction.Create(OpCodes.Stloc, resultVariable));
            }

            AddReturnCode(ins, resultVariable);

            body.OptimizeMacros();

            type.Methods.AddOrReplace(method);

            return(method);
        }