93 lines
3.1 KiB
C#
93 lines
3.1 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.Loader;
|
|
using Godot;
|
|
using OwofGames.GodotLume;
|
|
|
|
namespace GodotHostTest.GodotDI;
|
|
|
|
public static class ScopeTypesAndNames
|
|
{
|
|
private static readonly ConcurrentDictionary<Type, string> TypeToQualifiedName = new();
|
|
private static readonly ConcurrentDictionary<string, Type> QualifiedNameToType = new();
|
|
private static readonly ConcurrentDictionary<string, string> QualifiedNameToSimpleName = new();
|
|
private static readonly Type RootScopeType = typeof(RootScope);
|
|
|
|
private static AssemblyLoadEventHandler? _assemblyLoadEventHandler;
|
|
|
|
private static void InitializeIfNeeded()
|
|
{
|
|
if (_assemblyLoadEventHandler != null) return;
|
|
Initialize();
|
|
AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly())!.Unloading += OnUnloading;
|
|
}
|
|
|
|
private static void OnUnloading(AssemblyLoadContext _)
|
|
{
|
|
Deinitialize();
|
|
}
|
|
|
|
private static void Initialize()
|
|
{
|
|
GD.Print($"Initializing {nameof(ScopeTypesAndNames)}");
|
|
TypeToQualifiedName.Clear();
|
|
QualifiedNameToType.Clear();
|
|
QualifiedNameToSimpleName.Clear();
|
|
_assemblyLoadEventHandler = (sender, args) => CacheScriptsInAssembly(args.LoadedAssembly);
|
|
AppDomain.CurrentDomain.AssemblyLoad += _assemblyLoadEventHandler;
|
|
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
|
CacheScriptsInAssembly(assembly);
|
|
return;
|
|
|
|
void CacheScriptsInAssembly(Assembly assembly)
|
|
{
|
|
foreach (var type in assembly.GetTypes()
|
|
.Where(t => t.IsClass)
|
|
.Where(t => t == RootScopeType || t.IsSubclassOf(RootScopeType)))
|
|
{
|
|
if (type.AssemblyQualifiedName == null)
|
|
{
|
|
GD.PrintErr("Assembly qualified name of {type} is null");
|
|
continue;
|
|
}
|
|
|
|
TypeToQualifiedName[type] = type.AssemblyQualifiedName;
|
|
QualifiedNameToType[type.AssemblyQualifiedName] = type;
|
|
QualifiedNameToSimpleName[type.AssemblyQualifiedName] = type.Name;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void Deinitialize()
|
|
{
|
|
GD.Print($"Deinitializing {nameof(ScopeTypesAndNames)}");
|
|
AppDomain.CurrentDomain.AssemblyLoad -= _assemblyLoadEventHandler;
|
|
_assemblyLoadEventHandler = null;
|
|
TypeToQualifiedName.Clear();
|
|
QualifiedNameToType.Clear();
|
|
QualifiedNameToSimpleName.Clear();
|
|
}
|
|
|
|
public static IEnumerable<string> GetQualifiedNames()
|
|
{
|
|
InitializeIfNeeded();
|
|
return from p in TypeToQualifiedName
|
|
orderby p.Key == RootScopeType ? 0 : 1
|
|
select p.Value;
|
|
}
|
|
|
|
public static Type GetType(string qualifiedName)
|
|
{
|
|
InitializeIfNeeded();
|
|
return QualifiedNameToType[qualifiedName];
|
|
}
|
|
|
|
public static string GetSimpleNameFromQualifiedName(string qualifiedName)
|
|
{
|
|
InitializeIfNeeded();
|
|
return QualifiedNameToSimpleName[qualifiedName];
|
|
}
|
|
} |