From a36c93514dda0d31f9ee3f8f27a5b5a5ccb16c9d Mon Sep 17 00:00:00 2001 From: Robert Xiao Date: Mon, 13 Apr 2020 01:31:52 -0700 Subject: [PATCH] Implement NestedTypes for generic instances In the C# reflection API, DeclaredNestedTypes on concrete generic types just returns the nested types of the type definition. Notably, type parameters are not substituted, because nested types are not guaranteed to use the same containing type's type parameters. --- Il2CppInspector.Common/Reflection/TypeInfo.cs | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/Il2CppInspector.Common/Reflection/TypeInfo.cs b/Il2CppInspector.Common/Reflection/TypeInfo.cs index 3f42c74..9f2e89c 100644 --- a/Il2CppInspector.Common/Reflection/TypeInfo.cs +++ b/Il2CppInspector.Common/Reflection/TypeInfo.cs @@ -95,13 +95,26 @@ namespace Il2CppInspector.Reflection { public List DeclaredMembers => new IEnumerable[] { DeclaredConstructors, DeclaredEvents, DeclaredFields, DeclaredMethods, - DeclaredNestedTypes?.ToList() ?? new List(), DeclaredProperties + DeclaredNestedTypes, DeclaredProperties }.SelectMany(m => m).ToList(); public List DeclaredMethods { get; } = new List(); - private readonly int[] declaredNestedTypes; - public IEnumerable DeclaredNestedTypes => declaredNestedTypes.Select(x => Assembly.Model.TypesByDefinitionIndex[x]); + private readonly TypeRef[] declaredNestedTypes; + public IEnumerable DeclaredNestedTypes { + get { + if (declaredNestedTypes != null) + return declaredNestedTypes.Select(x => x.Value); + /* Type parameters are not substituted into nested classes, + * as nested classes aren't required to use the parameters + * from the containing class. + * This also matches the behaviour of the C# reflection API. + */ + if (genericTypeDefinition != null) + return genericTypeDefinition.DeclaredNestedTypes; + return Enumerable.Empty(); + } + } public List DeclaredProperties { get; } = new List(); @@ -656,9 +669,9 @@ namespace Il2CppInspector.Reflection { implementedInterfaceReferences[i] = TypeRef.FromReferenceIndex(Assembly.Model, pkg.InterfaceUsageIndices[Definition.interfacesStart + i]); // Add all nested types - declaredNestedTypes = new int[Definition.nested_type_count]; + declaredNestedTypes = new TypeRef[Definition.nested_type_count]; for (var n = 0; n < Definition.nested_type_count; n++) - declaredNestedTypes[n] = pkg.NestedTypeIndices[Definition.nestedTypesStart + n]; + declaredNestedTypes[n] = TypeRef.FromDefinitionIndex(Assembly.Model, pkg.NestedTypeIndices[Definition.nestedTypesStart + n]); // Add all fields for (var f = Definition.fieldStart; f < Definition.fieldStart + Definition.field_count; f++)