コード例 #1
0
        static void AddStaticEqualsCall(TypeDefinition type, Collection<Instruction> ins)
        {
            if (type.IsValueType)
            {
                var resolved = type.GetGenericInstanceType(type);
                ins.Add(Instruction.Create(OpCodes.Ldarg_0));
                ins.Add(Instruction.Create(OpCodes.Box, resolved));
                ins.Add(Instruction.Create(OpCodes.Ldarg_1));
                ins.Add(Instruction.Create(OpCodes.Box, resolved));
            }
            else
            {
                ins.Add(Instruction.Create(OpCodes.Ldarg_0));
                ins.Add(Instruction.Create(OpCodes.Ldarg_1));
            }

            ins.Add(Instruction.Create(OpCodes.Call, ReferenceFinder.Object.StaticEquals));
        }
コード例 #2
0
        static MethodDefinition AddOperator(TypeDefinition type, bool isEquality)
        {
            var methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Static;
            var method = new MethodDefinition(isEquality ? "op_Equality" : "op_Inequality", methodAttributes, ReferenceFinder.Boolean.TypeReference);
            method.CustomAttributes.MarkAsGeneratedCode();

            var parameterType = type.GetGenericInstanceType(type);

            method.Parameters.Add("left", parameterType);
            method.Parameters.Add("right", parameterType);

            var body = method.Body;
            var ins = body.Instructions;

            AddStaticEqualsCall(type, ins);
            AddReturnValue(isEquality, ins);

            body.OptimizeMacros();

            type.Methods.AddOrReplace(method);

            return method;
        }
コード例 #3
0
ファイル: EqualsInjector.cs プロジェクト: rjasica/Equals
        static void AddInternalEqualsCall(TypeDefinition type, TypeReference typeRef, MethodReference newEquals, Collection<Instruction> t, VariableDefinition result)
        {
            t.Add(Instruction.Create(OpCodes.Ldarg_0));
            if (type.IsValueType)
            {
                var resolvedType = type.GetGenericInstanceType(type);
                t.Add(Instruction.Create(OpCodes.Ldobj, resolvedType));
            }
            t.Add(Instruction.Create(OpCodes.Ldarg_1));
            if (type.IsValueType)
            {
                t.Add(Instruction.Create(OpCodes.Unbox_Any, typeRef));
            }
            else
            {
                t.Add(Instruction.Create(OpCodes.Castclass, typeRef));
            }

            t.Add(Instruction.Create(OpCodes.Call, newEquals));

            t.Add(Instruction.Create(OpCodes.Stloc, result));
        }
コード例 #4
0
ファイル: EqualsInjector.cs プロジェクト: rjasica/Equals
        static void AddExactlyTheSameTypeAsThis(TypeDefinition type, Collection<Instruction> c)
        {
            c.Add(Instruction.Create(OpCodes.Ldarg_0));
            if (type.IsValueType)
            {
                var resolved = type.GetGenericInstanceType(type);
                c.Add(Instruction.Create(OpCodes.Ldobj, resolved));
                c.Add(Instruction.Create(OpCodes.Box, resolved));
            }
            c.Add(Instruction.Create(OpCodes.Call, ReferenceFinder.Object.GetType));

            c.Add(Instruction.Create(OpCodes.Ldarg_1));
            c.Add(Instruction.Create(OpCodes.Callvirt, ReferenceFinder.Object.GetType));

            c.Add(Instruction.Create(OpCodes.Ceq));
        }
コード例 #5
0
ファイル: EqualsInjector.cs プロジェクト: rjasica/Equals
        static void AddExactlyOfType(TypeDefinition type, TypeReference typeRef, Collection<Instruction> c)
        {
            c.Add(Instruction.Create(OpCodes.Ldarg_0));
            if (type.IsValueType)
            {
                var resolved = type.GetGenericInstanceType(type);
                c.Add(Instruction.Create(OpCodes.Ldobj, resolved));
                c.Add(Instruction.Create(OpCodes.Box, resolved));
            }
            c.Add(Instruction.Create(OpCodes.Call, ReferenceFinder.Object.GetType));

            c.Add(Instruction.Create(OpCodes.Ldtoken, typeRef));
            c.Add(Instruction.Create(OpCodes.Call, ReferenceFinder.Type.GetTypeFromHandle));
            c.Add(Instruction.Create(OpCodes.Ceq));
        }
コード例 #6
0
ファイル: EqualsInjector.cs プロジェクト: rjasica/Equals
        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);
        }
コード例 #7
0
ファイル: EqualsInjector.cs プロジェクト: rjasica/Equals
        static void AddCheckEqualsReference(TypeDefinition type, Collection<Instruction> ins, bool skipBoxingSecond)
        {
            var resolvedType = type.IsValueType ? type.GetGenericInstanceType(type) : null;
            ins.If(
                c =>
                {
                    c.Add(Instruction.Create(OpCodes.Ldnull));
                    c.Add(Instruction.Create(OpCodes.Ldarg_1));
                    if (type.IsValueType && !skipBoxingSecond)
                    {
                        c.Add(Instruction.Create(OpCodes.Box, resolvedType));
                    }
                    c.Add(Instruction.Create(OpCodes.Call, ReferenceFinder.Object.ReferenceEquals));
                },
                AddReturnFalse);

            ins.If(
                c =>
                {
                    c.Add(Instruction.Create(OpCodes.Ldarg_0));
                    if (type.IsValueType)
                    {
                        c.Add(Instruction.Create(OpCodes.Ldobj, resolvedType));
                        c.Add(Instruction.Create(OpCodes.Box, resolvedType));
                    }
                    c.Add(Instruction.Create(OpCodes.Ldarg_1));
                    if (type.IsValueType && !skipBoxingSecond)
                    {
                        c.Add(Instruction.Create(OpCodes.Box, resolvedType));
                    }
                    c.Add(Instruction.Create(OpCodes.Call, ReferenceFinder.Object.ReferenceEquals));
                },
                AddReturnTrue);
        }