public static void DefineEqualsByPublicPropertiesMethod()

in src/Epam.GraphQL/Extensions/TypeBuilderExtensions.cs [215:275]


        public static void DefineEqualsByPublicPropertiesMethod(this TypeBuilder typeBuilder, IEnumerable<PropertyInfo> properties)
        {
            var equalsMethodInfo = _equalsMethodsInfo.GetOrAdd(typeBuilder.GetBaseType(), baseType => baseType.GetMethod(
                nameof(object.Equals),
                BindingFlags.Public | BindingFlags.Instance,
                null,
                new[] { typeof(object) },
                null));

            var equals = typeBuilder.DefineMethod(
                nameof(object.Equals),
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                typeof(bool),
                new[] { typeof(object) });

            typeBuilder.DefineMethodOverride(equals, equalsMethodInfo);

            var il = equals.GetILGenerator();
            il.DeclareLocal(typeBuilder);
            var retFalse = il.DefineLabel();
            var ret = il.DefineLabel();

            il
                .Ldarg(1)
                .Isinst(typeBuilder)
                .Stloc(0) // local = argument as the constructed type
                .Ldloc(0); // push result of the "as" operator

            foreach (var property in properties)
            {
                var defaultGetter = _equalityComparerDefaultGetters.GetOrAdd(
                    property.PropertyType,
                    type => typeof(EqualityComparer<>).MakeGenericType(type).GetProperty("Default", BindingFlags.Public | BindingFlags.Static).GetGetMethod());

                var equalsMethod = _equalityComparerEqualsMethods.GetOrAdd(
                    property.PropertyType,
                    type => typeof(EqualityComparer<>).MakeGenericType(type).GetMethod(
                        "Equals",
                        BindingFlags.Public | BindingFlags.Instance,
                        null,
                        new[] { property.PropertyType, property.PropertyType },
                        null));

                var getMethodInfo = property.GetGetMethod();
                il
                    .Brfalse(retFalse) // check if the result of the previous check is false
                    .Call(defaultGetter)
                    .Ldarg(0)
                    .Call(getMethodInfo)
                    .Ldloc(0)
                    .Call(getMethodInfo)
                    .Call(equalsMethod); // push EqualityComparer<FieldType>.Default.Equals(this.property, other.property)
            }

            il
                .BrS(ret) // jump to the end with what was the last result
                .PutLabel(retFalse)
                .LdcI4(0) // push false
                .PutLabel(ret)
                .Ret();
        }