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();
    }
}