in src/Epam.GraphQL/Extensions/DictionaryExtensions.cs [37:106]
public static Type MakeType(this IDictionary<string, Type> properties, string typeName, Type? parent = null)
{
Guards.ThrowIfNullOrEmpty(typeName, nameof(typeName));
return _typeCache.GetOrAdd((parent, typeName, properties), key =>
{
Interlocked.Increment(ref _typeCacheCount);
var (baseType, name, props) = key;
var baseTypeName = baseType == null || baseType == typeof(object) ? string.Empty : baseType.Name;
var baseTypeIsInterface = baseType != null && baseType.IsInterface;
var tb = ILUtils.DefineType($"<{baseTypeName}>__{name}`{_typeCacheCount}", baseTypeIsInterface ? null : baseType);
var propertyList = new List<PropertyBuilder>();
if (baseTypeIsInterface)
{
tb.AddInterfaceImplementation(baseType!);
foreach (var prop in baseType!.GetProperties())
{
var backingField = tb.DefineBackingField(prop.Name, prop.PropertyType);
propertyList.Add(tb.DefineProperty(backingField, prop.Name));
}
foreach (var baseInterface in baseType.GetInterfaces())
{
foreach (var prop in baseInterface.GetProperties())
{
var backingField = tb.DefineBackingField(prop.Name, prop.PropertyType);
propertyList.Add(tb.DefineProperty(backingField, prop.Name)); // TODO Check if baseInterface should be passed to DefineProperty for interfaces
}
}
foreach (var method in baseType.GetMethods().Concat(baseType.GetInterfaces().SelectMany(t => t.GetMethods())).Where(m => !m.IsSpecialName && m.IsAbstract))
{
tb.DefineNotImplementedMethodOverride(method);
}
}
else if (baseType != null)
{
foreach (var prop in baseType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => !p.CanWrite))
{
var backingField = tb.DefineBackingField(prop.Name, prop.PropertyType);
propertyList.Add(tb.DefineProperty(backingField, prop.Name));
}
}
tb.MakeCompilerGenerated();
foreach (var field in props)
{
var backingField = tb.DefineBackingField(field.Key, field.Value);
propertyList.Add(tb.DefineProperty(backingField, field.Key));
}
tb.SetDebuggerDisplayProperties(props.Select(p => p.Key));
tb.DefineEqualsByPublicPropertiesMethod(propertyList);
tb.DefineGetHashCodeByPublicPropertiesMethod(propertyList);
tb.DefineToStringByPublicPropertiesMethod(propertyList);
var objectType = tb.CreateTypeInfo();
// According to its signature, tb.CreateTypeInfo() can return null
Guards.ThrowNotSupportedIf(objectType == null);
return objectType!;
});
}