public static void DefineGetHashCodeByPublicPropertiesMethod()

in src/Epam.GraphQL/Extensions/TypeBuilderExtensions.cs [277:328]


        public static void DefineGetHashCodeByPublicPropertiesMethod(this TypeBuilder typeBuilder, IEnumerable<PropertyInfo> properties)
        {
            var getHasCodeMethodInfo = _getHashCodeMethodsInfo.GetOrAdd(
                typeBuilder.GetBaseType(),
                baseType => baseType.GetMethod(
                    nameof(object.GetHashCode),
                    BindingFlags.Public | BindingFlags.Instance,
                    null,
                    Type.EmptyTypes,
                    null));

            var getHashCode = typeBuilder.DefineMethod(
                nameof(object.GetHashCode),
                MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
                typeof(int),
                Type.EmptyTypes);

            typeBuilder.DefineMethodOverride(getHashCode, getHasCodeMethodInfo);

            var il = getHashCode.GetILGenerator();

            il
                .DeclareLocal<HashCode>()
                .DeclareLocal<int>()
                .Ldloca(0)
                .Initobj<HashCode>();

            foreach (var property in properties)
            {
                var comparer = typeof(EqualityComparer<>).MakeGenericType(property.PropertyType);
                var getMethodInfo = property.GetGetMethod();

                var addMethod = _hashCodeAddMethodsInfo.GetOrAdd(property.PropertyType, type =>
                {
                    _hashCodeAddMethodInfo ??= ReflectionHelpers.GetMethodInfo<object>(default(HashCode).Add<object>);
                    return _hashCodeAddMethodInfo.MakeGenericMethod(property.PropertyType);
                });

                il
                    .Ldloca(0)
                    .Ldarg(0)
                    .Call(getMethodInfo)
                    .Call(addMethod);
            }

            il
                .Ldloca(0)
                .Call(_hashCodeToHashCodeMethodInfo)
                .Stloc(1)
                .Ldloc(1)
                .Ret();
        }