public static void DefineToStringByPublicPropertiesMethod()

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