mirror of
https://github.com/sinai-dev/UnityExplorer.git
synced 2025-01-07 10:03:38 +08:00
Better EntryType checking for enumerables and dicts
This commit is contained in:
parent
e5d2d29a47
commit
5abfa3da67
@ -258,6 +258,18 @@ namespace UnityExplorer
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsAssignableFrom(Type thisType, Type fromType)
|
||||
{
|
||||
if (!Il2CppTypeNotNull(fromType, out IntPtr fromTypePtr)
|
||||
|| !Il2CppTypeNotNull(thisType, out IntPtr thisTypePtr))
|
||||
{
|
||||
// one or both of the types are not Il2Cpp types, use normal check
|
||||
return thisType.IsAssignableFrom(fromType);
|
||||
}
|
||||
|
||||
return il2cpp_class_is_assignable_from(thisTypePtr, fromTypePtr);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -508,7 +520,7 @@ namespace UnityExplorer
|
||||
#endregion
|
||||
|
||||
|
||||
#region Il2cpp reflection blacklist
|
||||
#region Il2cpp reflection blacklist
|
||||
|
||||
public override string DefaultReflectionBlacklist => string.Join(";", defaultIl2CppBlacklist);
|
||||
|
||||
@ -654,10 +666,54 @@ namespace UnityExplorer
|
||||
"UnityEngine.XR.InputDevice.SendHapticImpulse",
|
||||
};
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
|
||||
#region Temp il2cpp list/dictionary fixes
|
||||
protected override bool Internal_TryGetEntryType(Type enumerableType, out Type type)
|
||||
{
|
||||
// Check for system types (not unhollowed)
|
||||
if (base.Internal_TryGetEntryType(enumerableType, out type))
|
||||
return true;
|
||||
|
||||
// Type is either an IL2CPP enumerable, or its not generic.
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
// Temporary naive solution until IL2CPP interface support improves.
|
||||
// This will work fine for most cases, but there are edge cases which would not work.
|
||||
type = type.GetGenericArguments()[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Unable to determine entry type
|
||||
type = typeof(object);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override bool Internal_TryGetEntryTypes(Type type, out Type keys, out Type values)
|
||||
{
|
||||
if (base.Internal_TryGetEntryTypes(type, out keys, out values))
|
||||
return true;
|
||||
|
||||
// Type is either an IL2CPP dictionary, or its not generic.
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
// Naive solution until IL2CPP interfaces improve.
|
||||
var args = type.GetGenericArguments();
|
||||
if (args.Length == 2)
|
||||
{
|
||||
keys = args[0];
|
||||
values = args[1];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
keys = typeof(object);
|
||||
values = typeof(object);
|
||||
return false;
|
||||
}
|
||||
|
||||
#region Temp il2cpp list/dictionary fixes
|
||||
|
||||
// Temp fix until Unhollower interface support improves
|
||||
|
||||
|
@ -495,6 +495,39 @@ namespace UnityExplorer
|
||||
enumerator = (list as IEnumerable).GetEnumerator();
|
||||
return true;
|
||||
}
|
||||
|
||||
// TryGetEntryType
|
||||
|
||||
public static bool TryGetEntryType(Type enumerableType, out Type type)
|
||||
=> Instance.Internal_TryGetEntryType(enumerableType, out type);
|
||||
|
||||
protected virtual bool Internal_TryGetEntryType(Type enumerableType, out Type type)
|
||||
{
|
||||
// Check for arrays
|
||||
if (enumerableType.IsArray)
|
||||
{
|
||||
type = enumerableType.GetElementType();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for implementation of IEnumerable<T>, IList<T> or ICollection<T>
|
||||
foreach (var t in enumerableType.GetInterfaces())
|
||||
{
|
||||
if (t.IsGenericType)
|
||||
{
|
||||
var typeDef = t.GetGenericTypeDefinition();
|
||||
if (typeDef == typeof(IEnumerable<>) || typeDef == typeof(IList<>) || typeDef == typeof(ICollection<>))
|
||||
{
|
||||
type = t.GetGenericArguments()[0];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unable to determine any generic element type, just use object.
|
||||
type = typeof(object);
|
||||
return false;
|
||||
}
|
||||
|
||||
// IsDictionary
|
||||
|
||||
@ -524,5 +557,28 @@ namespace UnityExplorer
|
||||
yield return new DictionaryEntry(enumerator.Key, enumerator.Value);
|
||||
}
|
||||
}
|
||||
|
||||
// TryGetEntryTypes
|
||||
|
||||
public static bool TryGetEntryTypes(Type dictionaryType, out Type keys, out Type values)
|
||||
=> Instance.Internal_TryGetEntryTypes(dictionaryType, out keys, out values);
|
||||
|
||||
protected virtual bool Internal_TryGetEntryTypes(Type dictionaryType, out Type keys, out Type values)
|
||||
{
|
||||
foreach (var t in dictionaryType.GetInterfaces())
|
||||
{
|
||||
if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IDictionary<,>))
|
||||
{
|
||||
var args = t.GetGenericArguments();
|
||||
keys = args[0];
|
||||
values = args[1];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
keys = typeof(object);
|
||||
values = typeof(object);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
public override void Initialize()
|
||||
{
|
||||
ExplorerCore.Context = RuntimeContext.IL2CPP;
|
||||
//Reflection = new Il2CppReflection();
|
||||
TextureUtil = new Il2CppTextureUtil();
|
||||
}
|
||||
|
||||
@ -30,19 +29,12 @@ namespace UnityExplorer.Core.Runtime.Il2Cpp
|
||||
{
|
||||
try
|
||||
{
|
||||
//Application.add_logMessageReceived(new Action<string, string, LogType>(ExplorerCore.Instance.OnUnityLog));
|
||||
|
||||
var logType = ReflectionUtility.GetTypeByName("UnityEngine.Application+LogCallback");
|
||||
var castMethod = logType.GetMethod("op_Implicit", new[] { typeof(Action<string, string, LogType>) });
|
||||
var addMethod = typeof(Application).GetMethod("add_logMessageReceived", BF.Static | BF.Public, null, new[] { logType }, null);
|
||||
addMethod.Invoke(null, new[]
|
||||
{
|
||||
castMethod.Invoke(null, new[] { new Action<string, string, LogType>(Application_logMessageReceived) })
|
||||
});
|
||||
Application.add_logMessageReceived(new Action<string, string, LogType>(Application_logMessageReceived));
|
||||
}
|
||||
catch
|
||||
catch (Exception ex)
|
||||
{
|
||||
ExplorerCore.LogWarning("Exception setting up Unity log listener, make sure Unity libraries have been unstripped!");
|
||||
ExplorerCore.Log(ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using UnityExplorer.UI.CacheObject;
|
||||
@ -21,8 +22,8 @@ namespace UnityExplorer.UI.IValues
|
||||
|
||||
public override bool CanWrite => base.CanWrite && RefIDictionary != null && !RefIDictionary.IsReadOnly;
|
||||
|
||||
public Type KeyType;
|
||||
public Type ValueType;
|
||||
public Type KeysType;
|
||||
public Type ValuesType;
|
||||
public IDictionary RefIDictionary;
|
||||
|
||||
public int ItemCount => cachedEntries.Count;
|
||||
@ -75,24 +76,13 @@ namespace UnityExplorer.UI.IValues
|
||||
else
|
||||
{
|
||||
var type = value.GetActualType();
|
||||
|
||||
if (type.TryGetGenericArguments(out var args) && args.Length == 2)
|
||||
{
|
||||
KeyType = args[0];
|
||||
ValueType = args[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
KeyType = typeof(object);
|
||||
ValueType = typeof(object);
|
||||
}
|
||||
ReflectionUtility.TryGetEntryTypes(type, out KeysType, out ValuesType);
|
||||
|
||||
CacheEntries(value);
|
||||
|
||||
TopLabel.text = $"[{cachedEntries.Count}] {SignatureHighlighter.Parse(type, false)}";
|
||||
}
|
||||
|
||||
|
||||
this.DictScrollPool.Refresh(true, false);
|
||||
}
|
||||
|
||||
@ -117,7 +107,7 @@ namespace UnityExplorer.UI.IValues
|
||||
else
|
||||
cache = cachedEntries[idx];
|
||||
|
||||
cache.SetFallbackType(ValueType);
|
||||
cache.SetFallbackType(ValuesType);
|
||||
cache.SetKey(dictEnumerator.Current.Key);
|
||||
cache.SetValueFromSource(dictEnumerator.Current.Value);
|
||||
|
||||
|
@ -74,12 +74,7 @@ namespace UnityExplorer.UI.IValues
|
||||
else
|
||||
{
|
||||
var type = value.GetActualType();
|
||||
if (type.TryGetGenericArguments(out var args))
|
||||
EntryType = args[0];
|
||||
else if (type.HasElementType)
|
||||
EntryType = type.GetElementType();
|
||||
else
|
||||
EntryType = typeof(object);
|
||||
ReflectionUtility.TryGetEntryType(type, out EntryType);
|
||||
|
||||
CacheEntries(value);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user