feat: aetherbind, first source generator
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
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.AetherBind;
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user