Editor/TypeLibraryFixes/TypeCache.cs
using Editor;
using Sandbox;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
namespace ExtendedEditor.TypeLibraryFixes;
public static class TypeCache
{
private static readonly BindingFlags _instanceFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
[SkipHotload]
private static readonly ConcurrentDictionary<Type, ReadOnlyCollection<PropertyInfo>> _instanceProperties = [];
[SkipHotload]
private static readonly ConcurrentDictionary<Type, ReadOnlyCollection<FieldInfo>> _instanceFields = [];
[SkipHotload]
private static readonly ConcurrentDictionary<Type, ReadOnlyCollection<MethodInfo>> _instanceMethods = [];
public static IReadOnlyList<PropertyInfo> GetInstanceProperties(Type type)
{
if(_instanceProperties.TryGetValue(type, out var properties))
return properties;
return _instanceProperties.GetOrAdd(type, FindProperties(type, _instanceFlags));
}
public static IReadOnlyList<FieldInfo> GetInstanceFields(Type type)
{
if(_instanceFields.TryGetValue(type, out var fields))
return fields;
return _instanceFields.GetOrAdd(type, FindFields(type, _instanceFlags));
}
public static IReadOnlyList<MethodInfo> GetInstanceMethods(Type type)
{
if(_instanceMethods.TryGetValue(type, out var fields))
return fields;
return _instanceMethods.GetOrAdd(type, FindMethods(type, _instanceFlags));
}
private static ReadOnlyCollection<PropertyInfo> FindProperties(Type type, BindingFlags bindingFlags)
{
return type.GetProperties(bindingFlags).Where(IsValidMember).ToArray().AsReadOnly();
}
private static ReadOnlyCollection<FieldInfo> FindFields(Type type, BindingFlags bindingFlags)
{
return type.GetFields(bindingFlags).Where(IsValidMember).ToArray().AsReadOnly();
}
private static ReadOnlyCollection<MethodInfo> FindMethods(Type type, BindingFlags bindingFlags)
{
return type.GetMethods(bindingFlags).Where(IsValidMember).ToArray().AsReadOnly();
}
private static bool IsValidMember(MemberInfo memberInfo)
{
var declaringType = memberInfo.DeclaringType;
if(declaringType == typeof(object) ||
declaringType == typeof(GameObject) ||
declaringType == typeof(Component) ||
declaringType == typeof(Resource) ||
declaringType == typeof(GameResource)
)
return false;
if(memberInfo.GetCustomAttribute<CompilerGeneratedAttribute>() is not null)
return false;
var name = memberInfo.Name;
if(name.StartsWith("__") ||
name.StartsWith('<') ||
name.StartsWith("get_") ||
name.StartsWith("set_")
)
return false;
return true;
}
[EditorEvent.Hotload]
private static void OnHotload()
{
_instanceProperties.Clear();
_instanceFields.Clear();
}
}