From 95e8b3aa584199e1f31c211feb3091da5e449177 Mon Sep 17 00:00:00 2001 From: Sinai Date: Wed, 7 Apr 2021 17:31:06 +1000 Subject: [PATCH] fix string unbox --- src/Core/Runtime/Il2Cpp/Il2CppReflection.cs | 121 +++++++++--------- src/UI/InteractiveValues/InteractiveString.cs | 3 +- 2 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs b/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs index 1513b0f..8d10743 100644 --- a/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs +++ b/src/Core/Runtime/Il2Cpp/Il2CppReflection.cs @@ -44,6 +44,31 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp } } + public override void BoxStringToType(ref object value, Type castTo) + { + if (castTo == typeof(Il2CppSystem.String)) + value = (Il2CppSystem.String)(value as string); + else + value = (Il2CppSystem.Object)(value as string); + } + + public override string UnboxString(object value) + { + if (value is string s) + return s; + + s = null; + // strings boxed as Il2CppSystem.Objects can behave weirdly. + // GetActualType will find they are a string, but if its boxed + // then we need to unbox it like this... + if (value is Il2CppSystem.Object cppObject) + s = cppObject.ToString(); + else if (value is Il2CppSystem.String cppString) + s = cppString; + + return s; + } + public override string ProcessTypeNameInString(Type type, string theString, ref string typeName) { if (!Il2CppTypeNotNull(type)) @@ -334,64 +359,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp return false; } - public override void BoxStringToType(ref object value, Type castTo) - { - if (castTo == typeof(Il2CppSystem.String)) - value = (Il2CppSystem.String)(value as string); - else - value = (Il2CppSystem.Object)(value as string); - } - - // ~~~~~~~~~~ not used ~~~~~~~~~~~~ - - // cached il2cpp unbox methods - internal static readonly Dictionary s_unboxMethods = new Dictionary(); - - /// - /// Attempt to unbox the object to the underlying struct type. - /// - /// The object which is a struct underneath. - /// The struct if successful, otherwise null. - public static object Unbox(object obj) => Unbox(obj, Instance.GetActualType(obj)); - - /// - /// Attempt to unbox the object to the struct type. - /// - /// The object which is a struct underneath. - /// The type of the struct you want to unbox to. - /// The struct if successful, otherwise null. - public static object Unbox(object obj, Type type) - { - if (!type.IsValueType) - return null; - - if (!(obj is Il2CppSystem.Object)) - return obj; - - var name = type.AssemblyQualifiedName; - - if (!s_unboxMethods.ContainsKey(name)) - { - s_unboxMethods.Add(name, typeof(Il2CppObjectBase) - .GetMethod("Unbox") - .MakeGenericMethod(type)); - } - - return s_unboxMethods[name].Invoke(obj, new object[0]); - } - - public override string UnboxString(object value) - { - string s = null; - // strings boxed as Il2CppSystem.Objects can behave weirdly. - // GetActualType will find they are a string, but if its boxed - // then we need to unbox it like this... - if (!(value is string) && value is Il2CppSystem.Object cppobj) - s = cppobj.ToString(); - - return s; - } - internal static readonly Dictionary s_getEnumeratorMethods = new Dictionary(); internal static readonly Dictionary s_enumeratorInfos = new Dictionary(); @@ -497,6 +464,44 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp values.Add(bucket.val); } } + + // ~~~~~~~~~~ not used ~~~~~~~~~~~~ + + // cached il2cpp unbox methods + internal static readonly Dictionary s_unboxMethods = new Dictionary(); + + /// + /// Attempt to unbox the object to the underlying struct type. + /// + /// The object which is a struct underneath. + /// The struct if successful, otherwise null. + public static object Unbox(object obj) => Unbox(obj, Instance.GetActualType(obj)); + + /// + /// Attempt to unbox the object to the struct type. + /// + /// The object which is a struct underneath. + /// The type of the struct you want to unbox to. + /// The struct if successful, otherwise null. + public static object Unbox(object obj, Type type) + { + if (!type.IsValueType) + return null; + + if (!(obj is Il2CppSystem.Object)) + return obj; + + var name = type.AssemblyQualifiedName; + + if (!s_unboxMethods.ContainsKey(name)) + { + s_unboxMethods.Add(name, typeof(Il2CppObjectBase) + .GetMethod("Unbox") + .MakeGenericMethod(type)); + } + + return s_unboxMethods[name].Invoke(obj, new object[0]); + } } } diff --git a/src/UI/InteractiveValues/InteractiveString.cs b/src/UI/InteractiveValues/InteractiveString.cs index ed5c8ad..c14d758 100644 --- a/src/UI/InteractiveValues/InteractiveString.cs +++ b/src/UI/InteractiveValues/InteractiveString.cs @@ -24,7 +24,8 @@ namespace UnityExplorer.UI.InteractiveValues public override void OnValueUpdated() { - Value = RuntimeProvider.Instance.Reflection.UnboxString(Value); + if (!(Value is string) && Value != null) + Value = RuntimeProvider.Instance.Reflection.UnboxString(Value); base.OnValueUpdated(); }