From adc52818fb4ffb61c7f640a88d3cc90c97ac757e Mon Sep 17 00:00:00 2001 From: Katy Coe Date: Sat, 18 Jan 2020 21:30:34 +0100 Subject: [PATCH] Model: Detect and fix orphan property methods --- .../Reflection/CustomAttributeData.cs | 5 ++- Il2CppInspector/Reflection/PropertyInfo.cs | 13 ++++++- Il2CppInspector/Reflection/TypeInfo.cs | 37 +++++++++++++++++-- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/Il2CppInspector/Reflection/CustomAttributeData.cs b/Il2CppInspector/Reflection/CustomAttributeData.cs index bf587d1..e94d337 100644 --- a/Il2CppInspector/Reflection/CustomAttributeData.cs +++ b/Il2CppInspector/Reflection/CustomAttributeData.cs @@ -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 GetCustomAttributes(FieldInfo field) => getCustomAttributes(field.Assembly, field.Definition.token, field.Definition.customAttributeIndex); public static IList GetCustomAttributes(MethodBase method) => getCustomAttributes(method.Assembly, method.Definition.token, method.Definition.customAttributeIndex); public static IList GetCustomAttributes(ParameterInfo param) => getCustomAttributes(param.DeclaringMethod.Assembly, param.Definition.token, param.Definition.customAttributeIndex); - public static IList GetCustomAttributes(PropertyInfo prop) => getCustomAttributes(prop.Assembly, prop.Definition.token, prop.Definition.customAttributeIndex); + public static IList GetCustomAttributes(PropertyInfo prop) + => prop.Definition != null ? getCustomAttributes(prop.Assembly, prop.Definition.token, prop.Definition.customAttributeIndex) : new List(); public static IList GetCustomAttributes(TypeInfo type) => getCustomAttributes(type.Assembly, type.Definition.token, type.Definition.customAttributeIndex); } } diff --git a/Il2CppInspector/Reflection/PropertyInfo.cs b/Il2CppInspector/Reflection/PropertyInfo.cs index bb86b94..ab1d519 100644 --- a/Il2CppInspector/Reflection/PropertyInfo.cs +++ b/Il2CppInspector/Reflection/PropertyInfo.cs @@ -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; + } } } \ No newline at end of file diff --git a/Il2CppInspector/Reflection/TypeInfo.cs b/Il2CppInspector/Reflection/TypeInfo.cs index e1d57e9..1b8867b 100644 --- a/Il2CppInspector/Reflection/TypeInfo.cs +++ b/Il2CppInspector/Reflection/TypeInfo.cs @@ -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++)