in src/Epam.GraphQL/Extensions/TypeBuilderExtensions.cs [330:378]
public static void DefineToStringByPublicPropertiesMethod(this TypeBuilder typeBuilder, IEnumerable<PropertyInfo> properties)
{
var toStringMethodInfo = _toStringMethodsInfo.GetOrAdd(
typeBuilder.GetBaseType(),
baseType => baseType.GetMethod(
nameof(object.ToString),
BindingFlags.Public | BindingFlags.Instance,
null,
Type.EmptyTypes,
null));
var toString = typeBuilder.DefineMethod(
nameof(object.ToString),
MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual,
typeof(string),
Type.EmptyTypes);
typeBuilder.DefineMethodOverride(toString, toStringMethodInfo);
var propertyArray = properties.ToArray();
var template = $"{{{{ {string.Join(", ", propertyArray.Select((p, i) => $"{p.Name} = {{{i}}}"))} }}}}";
var il = toString.GetILGenerator();
il
.Ldstr(template) // push template
.LdcI4(propertyArray.Length) // push new array
.Newarr<object>();
var index = 0;
foreach (var property in propertyArray)
{
var getMethodInfo = property.GetGetMethod();
il
.Dup() // duplicate array ref
.LdcI4(index) // push array index
.Ldarg(0)
.Call(getMethodInfo)
.Box(property.PropertyType)
.Stelem<object>();
index++;
}
il
.Call(_stringFormat)
.Ret();
}