Model: Detect and fix orphan property methods

This commit is contained in:
Katy Coe
2020-01-18 21:30:34 +01:00
parent 64b263bafb
commit adc52818fb
3 changed files with 48 additions and 7 deletions

View File

@@ -1,5 +1,5 @@
/*
Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
All rights reserved.
*/
@@ -68,7 +68,8 @@ namespace Il2CppInspector.Reflection
public static IList<CustomAttributeData> GetCustomAttributes(FieldInfo field) => getCustomAttributes(field.Assembly, field.Definition.token, field.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(MethodBase method) => getCustomAttributes(method.Assembly, method.Definition.token, method.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(ParameterInfo param) => getCustomAttributes(param.DeclaringMethod.Assembly, param.Definition.token, param.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(PropertyInfo prop) => getCustomAttributes(prop.Assembly, prop.Definition.token, prop.Definition.customAttributeIndex);
public static IList<CustomAttributeData> GetCustomAttributes(PropertyInfo prop)
=> prop.Definition != null ? getCustomAttributes(prop.Assembly, prop.Definition.token, prop.Definition.customAttributeIndex) : new List<CustomAttributeData>();
public static IList<CustomAttributeData> GetCustomAttributes(TypeInfo type) => getCustomAttributes(type.Assembly, type.Definition.token, type.Definition.customAttributeIndex);
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
All rights reserved.
*/
@@ -57,5 +57,16 @@ namespace Il2CppInspector.Reflection {
if (Definition.set >= 0)
SetMethod = declaringType.DeclaredMethods.First(x => x.Index == declaringType.Definition.methodStart + Definition.set);
}
// Create a property based on a get and set method
public PropertyInfo(MethodInfo getter, MethodInfo setter, TypeInfo declaringType) :
base(declaringType) {
Index = -1;
Definition = null;
Name = (getter ?? setter).Name.Replace(".get_", ".").Replace(".set_", ".");
GetMethod = getter;
SetMethod = setter;
}
}
}

View File

@@ -1,12 +1,11 @@
/*
Copyright 2017-2019 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
Copyright 2017-2020 Katy Coe - http://www.hearthcode.org - http://www.djkaty.com
All rights reserved.
*/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
@@ -523,9 +522,39 @@ namespace Il2CppInspector.Reflection {
for (var p = Definition.propertyStart; p < Definition.propertyStart + Definition.property_count; p++)
DeclaredProperties.Add(new PropertyInfo(pkg, p, this));
// There are rare cases when properties are only given as methods in the metadata
// Find these and add them as properties
// There are rare cases when explicitly implemented interface properties
// are only given as methods in the metadata. Find these and add them as properties
var eip = DeclaredMethods.Where(m => m.Name.Contains(".get_") || m.Name.Contains(".set_"))
.Except(DeclaredProperties.Select(p => p.GetMethod))
.Except(DeclaredProperties.Select(p => p.SetMethod));
// Build a paired list of getters and setters
var pairedEip = new List<(MethodInfo get, MethodInfo set)>();
foreach (var p in eip) {
// Discern property name
var n = p.Name.Replace(".get_", ".").Replace(".set_", ".");
// Find setter with no matching getter
if (p.Name.Contains(".get_"))
if (pairedEip.FirstOrDefault(pe => pe.get == null && pe.set.Name == p.Name.Replace(".get_", ".set_")) is (MethodInfo get, MethodInfo set) method) {
pairedEip.Remove(method);
pairedEip.Add((p, method.set));
}
else
pairedEip.Add((p, null));
// Find getter with no matching setter
if (p.Name.Contains(".set_"))
if (pairedEip.FirstOrDefault(pe => pe.set == null && pe.get.Name == p.Name.Replace(".set_", ".get_")) is (MethodInfo get, MethodInfo set) method) {
pairedEip.Remove(method);
pairedEip.Add((method.get, p));
}
else
pairedEip.Add((null, p));
}
foreach (var prop in pairedEip)
DeclaredProperties.Add(new PropertyInfo(prop.get, prop.set, this));
// Add all events
for (var e = Definition.eventStart; e < Definition.eventStart + Definition.event_count; e++)