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:
@@ -76,6 +76,7 @@ namespace Il2CppInspector.Reflection
|
||||
return this;
|
||||
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
|
||||
public bool IsGenericMethod { get; }
|
||||
|
||||
@@ -77,7 +77,9 @@ namespace Il2CppInspector.Reflection {
|
||||
rootDefinition = propertyDef;
|
||||
|
||||
Name = propertyDef.Name;
|
||||
if (propertyDef.GetMethod != null)
|
||||
GetMethod = declaringType.GetMethodByDefinition(propertyDef.GetMethod);
|
||||
if (propertyDef.SetMethod != null)
|
||||
SetMethod = declaringType.GetMethodByDefinition(propertyDef.SetMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,7 +210,7 @@ namespace Il2CppInspector.Reflection
|
||||
if (genericTypeDefinition != null) {
|
||||
var collection = genericTypeDefinition.DeclaredConstructors;
|
||||
for (int i = 0; i < collection.Count; i++) {
|
||||
if (collection[i] == definition)
|
||||
if (collection[i].RootDefinition == definition.RootDefinition)
|
||||
return DeclaredConstructors[i];
|
||||
}
|
||||
}
|
||||
@@ -222,7 +222,7 @@ namespace Il2CppInspector.Reflection
|
||||
if (genericTypeDefinition != null) {
|
||||
var collection = genericTypeDefinition.DeclaredMethods;
|
||||
for (int i = 0; i < collection.Count; i++) {
|
||||
if (collection[i] == definition)
|
||||
if (collection[i].RootDefinition == definition.RootDefinition)
|
||||
return DeclaredMethods[i];
|
||||
}
|
||||
}
|
||||
@@ -250,15 +250,29 @@ namespace Il2CppInspector.Reflection
|
||||
public PropertyInfo GetProperty(string name) => DeclaredProperties.FirstOrDefault(p => p.Name == name);
|
||||
|
||||
public MethodBase[] GetVTable() {
|
||||
var definition = Definition;
|
||||
|
||||
MetadataUsage[] vt = Assembly.Model.Package.GetVTable(definition);
|
||||
if (Definition != null) {
|
||||
MetadataUsage[] vt = Assembly.Model.Package.GetVTable(Definition);
|
||||
MethodBase[] res = new MethodBase[vt.Length];
|
||||
for (int i = 0; i < vt.Length; i++) {
|
||||
if (vt[i] != null)
|
||||
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 null;
|
||||
}
|
||||
|
||||
// Method that the type is declared in if this is a type parameter of a generic method
|
||||
|
||||
Reference in New Issue
Block a user