Add generics support to TypeInfo.GetVTable

This patch fixes TypeInfo.GetVTable so that it specializes the vtable
for generic type instances. Also fix a minor bug in PropertyInfo that
would pass null pointers to GetMethodByDefinition.
This commit is contained in:
Robert Xiao
2020-04-20 00:11:31 -07:00
committed by Katy
parent 359b99fded
commit 4ba48b9c75
3 changed files with 29 additions and 12 deletions

View File

@@ -76,6 +76,7 @@ namespace Il2CppInspector.Reflection
return this; return this;
throw new InvalidOperationException("This method can only be called on generic methods"); throw new InvalidOperationException("This method can only be called on generic methods");
} }
public MethodBase RootDefinition => rootDefinition;
// See: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.methodbase.isgenericmethod?view=netframework-4.8 // See: https://docs.microsoft.com/en-us/dotnet/api/system.reflection.methodbase.isgenericmethod?view=netframework-4.8
public bool IsGenericMethod { get; } public bool IsGenericMethod { get; }

View File

@@ -77,8 +77,10 @@ namespace Il2CppInspector.Reflection {
rootDefinition = propertyDef; rootDefinition = propertyDef;
Name = propertyDef.Name; Name = propertyDef.Name;
GetMethod = declaringType.GetMethodByDefinition(propertyDef.GetMethod); if (propertyDef.GetMethod != null)
SetMethod = declaringType.GetMethodByDefinition(propertyDef.SetMethod); GetMethod = declaringType.GetMethodByDefinition(propertyDef.GetMethod);
if (propertyDef.SetMethod != null)
SetMethod = declaringType.GetMethodByDefinition(propertyDef.SetMethod);
} }
} }
} }

View File

@@ -210,7 +210,7 @@ namespace Il2CppInspector.Reflection
if (genericTypeDefinition != null) { if (genericTypeDefinition != null) {
var collection = genericTypeDefinition.DeclaredConstructors; var collection = genericTypeDefinition.DeclaredConstructors;
for (int i = 0; i < collection.Count; i++) { for (int i = 0; i < collection.Count; i++) {
if (collection[i] == definition) if (collection[i].RootDefinition == definition.RootDefinition)
return DeclaredConstructors[i]; return DeclaredConstructors[i];
} }
} }
@@ -222,7 +222,7 @@ namespace Il2CppInspector.Reflection
if (genericTypeDefinition != null) { if (genericTypeDefinition != null) {
var collection = genericTypeDefinition.DeclaredMethods; var collection = genericTypeDefinition.DeclaredMethods;
for (int i = 0; i < collection.Count; i++) { for (int i = 0; i < collection.Count; i++) {
if (collection[i] == definition) if (collection[i].RootDefinition == definition.RootDefinition)
return DeclaredMethods[i]; return DeclaredMethods[i];
} }
} }
@@ -250,15 +250,29 @@ namespace Il2CppInspector.Reflection
public PropertyInfo GetProperty(string name) => DeclaredProperties.FirstOrDefault(p => p.Name == name); public PropertyInfo GetProperty(string name) => DeclaredProperties.FirstOrDefault(p => p.Name == name);
public MethodBase[] GetVTable() { public MethodBase[] GetVTable() {
var definition = Definition; if (Definition != null) {
MetadataUsage[] vt = Assembly.Model.Package.GetVTable(Definition);
MetadataUsage[] vt = Assembly.Model.Package.GetVTable(definition); MethodBase[] res = new MethodBase[vt.Length];
MethodBase[] res = new MethodBase[vt.Length]; for (int i = 0; i < vt.Length; i++) {
for (int i = 0; i < vt.Length; i++) { if (vt[i] != null)
if (vt[i] != null) res[i] = Assembly.Model.GetMetadataUsageMethod(vt[i]);
res[i] = Assembly.Model.GetMetadataUsageMethod(vt[i]); }
return res;
} else if (genericTypeDefinition != null) {
MethodBase[] baseVt = genericTypeDefinition.GetVTable();
MethodBase[] res = new MethodBase[baseVt.Length];
for (int i = 0; i < baseVt.Length; i++) {
if (baseVt[i] == null)
continue;
var declaringType = baseVt[i].DeclaringType.SubstituteGenericArguments(genericArguments);
if (baseVt[i] is ConstructorInfo ci)
res[i] = declaringType.GetConstructorByDefinition(ci);
else
res[i] = declaringType.GetMethodByDefinition((MethodInfo)baseVt[i]);
}
return res;
} }
return res; return null;
} }
// Method that the type is declared in if this is a type parameter of a generic method // Method that the type is declared in if this is a type parameter of a generic method