Ejemplo n.º 1
0
            private MethodDefinition OverrideObjectEquals(TypeDefinition caseClassTypeDefinition, MethodDefinition typedEqualsMethod)
            {
                var method = new MethodDefinition(
                    nameof(object.Equals),
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                    _typeSystem.BooleanReference);

                var otherInstance = new ParameterDefinition("obj", ParameterAttributes.None, _typeSystem.ObjectReference);

                method.Parameters.Add(otherInstance);
                var compareCodeEmitter = method.Body.GetILProcessor();

                var concreteCaseClass = caseClassTypeDefinition.AsConcreteTypeReference();

                compareCodeEmitter.Emit(OpCodes.Ldarg_0);
                compareCodeEmitter.Emit(OpCodes.Ldarg_1);
                compareCodeEmitter.Emit(OpCodes.Isinst, concreteCaseClass);
                if (concreteCaseClass is GenericInstanceType)
                {
                    var methodToCall = new MethodReference(typedEqualsMethod.Name, typedEqualsMethod.ReturnType, concreteCaseClass)
                    {
                        HasThis = true
                    };
                    methodToCall.Parameters.Add(new ParameterDefinition("other", ParameterAttributes.None, concreteCaseClass));
                    compareCodeEmitter.Emit(OpCodes.Call, methodToCall);
                }
                else
                {
                    compareCodeEmitter.Emit(OpCodes.Call, typedEqualsMethod);
                }
                compareCodeEmitter.Emit(OpCodes.Ret);

                return(method);
            }
Ejemplo n.º 2
0
        public TypeReference MarkAsImplementedBy(TypeDefinition classDefinition)
        {
            var concreteClassType = classDefinition.AsConcreteTypeReference();
            var concreteInterface = _types.GenericIEquatable.MakeGenericInstanceType(concreteClassType);

            classDefinition.Interfaces.Add(new InterfaceImplementation(concreteInterface));
            return(concreteClassType);
        }
Ejemplo n.º 3
0
            private MethodDefinition MakeEqualityOperator(TypeDefinition caseClassTypeDefinition, bool equality)
            {
                var method = new MethodDefinition(
                    equality ? "op_Equality" : "op_Inequality",
                    MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.Static,
                    _typeSystem.BooleanReference);

                var concreteCaseClassType = caseClassTypeDefinition.AsConcreteTypeReference();
                var leftInstance          = new ParameterDefinition("left", ParameterAttributes.None, concreteCaseClassType);
                var rightInstance         = new ParameterDefinition("right", ParameterAttributes.None, concreteCaseClassType);

                method.Parameters.Add(leftInstance);
                method.Parameters.Add(rightInstance);

                var compareCodeEmitter = method.Body.GetILProcessor();

                compareCodeEmitter.Emit(OpCodes.Ldarg_0);
                compareCodeEmitter.Emit(OpCodes.Ldarg_1);
                var methodToCall              = _deepEqualityComparer.GetMethods().Single(m => m.Name == nameof(DeepEqualityComparer.EquatableReferencesAreEqual));
                var genericMethod             = new GenericInstanceMethod(_moduleDefinition.ImportReference(methodToCall));
                var referencedGenericArgument = concreteCaseClassType;

                genericMethod.GenericArguments.Add(referencedGenericArgument);
                compareCodeEmitter.Emit(OpCodes.Call, genericMethod);

                if (equality)
                {
                    compareCodeEmitter.Emit(OpCodes.Ret);
                }
                else
                {
                    var keepAnalyzingProperties = Instruction.Create(OpCodes.Ldc_I4_0);
                    compareCodeEmitter.Emit(OpCodes.Ldc_I4_0);
                    compareCodeEmitter.Emit(OpCodes.Ceq);
                    compareCodeEmitter.Emit(OpCodes.Brfalse_S, keepAnalyzingProperties);
                    compareCodeEmitter.Emit(OpCodes.Ldc_I4_1);
                    compareCodeEmitter.Emit(OpCodes.Ret);
                    compareCodeEmitter.Append(keepAnalyzingProperties);
                    compareCodeEmitter.Emit(OpCodes.Ret);
                }

                return(method);
            }