Use recursive GetGenericArguments to catch unusual type structures, cleanup InteractiveList value caching

This commit is contained in:
Sinai 2021-05-18 20:55:18 +10:00
parent 496a5de55e
commit ac9c2d5286
3 changed files with 32 additions and 15 deletions

View File

@ -36,6 +36,27 @@ namespace UnityExplorer
// ------- Misc extensions --------
/// <summary>
/// Recursively check the type and its base types to find any generic arguments.
/// </summary>
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;
}
}
/// <summary>
/// Safely try to get all Types inside an Assembly.
/// </summary>

View File

@ -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
{

View File

@ -28,8 +28,7 @@ namespace UnityExplorer.UI.IValues
private bool IsWritableGenericIList;
private PropertyInfo genericIndexer;
public int ItemCount => values.Count;
private readonly List<object> values = new List<object>();
public int ItemCount => cachedEntries.Count;
private readonly List<CacheListEntry> cachedEntries = new List<CacheListEntry>();
public ScrollPool<CacheListEntryCell> 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)