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();
}