From ac9c2d52866619724d4e4e2998231ded7d8d7841 Mon Sep 17 00:00:00 2001 From: Sinai Date: Tue, 18 May 2021 20:55:18 +1000 Subject: [PATCH] Use recursive GetGenericArguments to catch unusual type structures, cleanup InteractiveList value caching --- src/Core/Reflection/Extensions.cs | 21 +++++++++++++++++++++ src/UI/IValues/InteractiveDictionary.cs | 9 +++++---- src/UI/IValues/InteractiveList.cs | 17 ++++++----------- 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/src/Core/Reflection/Extensions.cs b/src/Core/Reflection/Extensions.cs index f948fd5..98393ef 100644 --- a/src/Core/Reflection/Extensions.cs +++ b/src/Core/Reflection/Extensions.cs @@ -36,6 +36,27 @@ namespace UnityExplorer // ------- Misc extensions -------- + /// + /// Recursively check the type and its base types to find any generic arguments. + /// + public static bool TryGetGenericArguments(this Type type, out Type[] args) + { + if (type.IsGenericType) + { + args = type.GetGenericArguments(); + return true; + } + else if (type.BaseType != null) + { + return TryGetGenericArguments(type.BaseType, out args); + } + else + { + args = null; + return false; + } + } + /// /// Safely try to get all Types inside an Assembly. /// diff --git a/src/UI/IValues/InteractiveDictionary.cs b/src/UI/IValues/InteractiveDictionary.cs index f17c447..e49161c 100644 --- a/src/UI/IValues/InteractiveDictionary.cs +++ b/src/UI/IValues/InteractiveDictionary.cs @@ -75,10 +75,11 @@ namespace UnityExplorer.UI.IValues else { var type = value.GetActualType(); - if (type.IsGenericType && type.GetGenericArguments().Length == 2) - { - KeyType = type.GetGenericArguments()[0]; - ValueType = type.GetGenericArguments()[1]; + + if (type.TryGetGenericArguments(out var args) && args.Length == 2) + { + KeyType = args[0]; + ValueType = args[1]; } else { diff --git a/src/UI/IValues/InteractiveList.cs b/src/UI/IValues/InteractiveList.cs index 16a13ed..6a1f6be 100644 --- a/src/UI/IValues/InteractiveList.cs +++ b/src/UI/IValues/InteractiveList.cs @@ -28,8 +28,7 @@ namespace UnityExplorer.UI.IValues private bool IsWritableGenericIList; private PropertyInfo genericIndexer; - public int ItemCount => values.Count; - private readonly List values = new List(); + public int ItemCount => cachedEntries.Count; private readonly List cachedEntries = new List(); public ScrollPool ListScrollPool { get; private set; } @@ -53,7 +52,6 @@ namespace UnityExplorer.UI.IValues private void ClearAndRelease() { RefIList = null; - values.Clear(); foreach (var entry in cachedEntries) { @@ -70,14 +68,14 @@ namespace UnityExplorer.UI.IValues if (value == null) { // should never be null - if (values.Any()) + if (cachedEntries.Any()) ClearAndRelease(); } else { var type = value.GetActualType(); - if (type.IsGenericType) - EntryType = type.GetGenericArguments()[0]; + if (type.TryGetGenericArguments(out var args)) + EntryType = args[0]; else if (type.HasElementType) EntryType = type.GetElementType(); else @@ -102,7 +100,6 @@ namespace UnityExplorer.UI.IValues else IsWritableGenericIList = false; - values.Clear(); int idx = 0; if (ReflectionUtility.TryGetEnumerator(value, out IEnumerator enumerator)) @@ -113,8 +110,6 @@ namespace UnityExplorer.UI.IValues { var entry = enumerator.Current; - values.Add(entry); - // If list count increased, create new cache entries CacheListEntry cache; if (idx >= cachedEntries.Count) @@ -132,9 +127,9 @@ namespace UnityExplorer.UI.IValues } // Remove excess cached entries if list count decreased - if (cachedEntries.Count > values.Count) + if (cachedEntries.Count > idx) { - for (int i = cachedEntries.Count - 1; i >= values.Count; i--) + for (int i = cachedEntries.Count - 1; i >= idx; i--) { var cache = cachedEntries[i]; if (cache.CellView != null)