using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Security.Cryptography; using System.Text; using Fantasy.Async; using Fantasy.Helper; #pragma warning disable CS8604 // Possible null reference argument. #pragma warning disable CS8602 // Dereference of a possibly null reference. #pragma warning disable CS8603 #pragma warning disable CS8618 namespace Fantasy.Assembly { /// /// 管理程序集加载和卸载的帮助类。 /// public static class AssemblySystem { #if FANTASY_WEBGL private static readonly List AssemblySystems = new List(); private static readonly Dictionary AssemblyList = new Dictionary(); #else private static readonly ConcurrentQueue AssemblySystems = new ConcurrentQueue(); private static readonly ConcurrentDictionary AssemblyList = new ConcurrentDictionary(); #endif /// /// 初始化 AssemblySystem。(仅限内部) /// /// internal static async FTask InnerInitialize(params System.Reflection.Assembly[] assemblies) { await LoadAssembly(typeof(AssemblySystem).Assembly); foreach (var assembly in assemblies) { await LoadAssembly(assembly); } } /// /// 加载指定的程序集,并触发相应的事件。 /// /// 要加载的程序集。 /// 如果当前Domain中已经存在同名的Assembly,使用Domain中的程序集。 public static async FTask LoadAssembly(System.Reflection.Assembly assembly, bool isCurrentDomain = true) { if (isCurrentDomain) { var currentDomainAssemblies = System.AppDomain.CurrentDomain.GetAssemblies(); var currentAssembly = currentDomainAssemblies.FirstOrDefault(d => d.GetName().Name == assembly.GetName().Name); if (currentAssembly != null) { assembly = currentAssembly; } } var assemblyIdentity = AssemblyIdentity(assembly); if (AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo)) { assemblyInfo.ReLoad(assembly); foreach (var assemblySystem in AssemblySystems) { await assemblySystem.ReLoad(assemblyIdentity); } } else { assemblyInfo = new AssemblyInfo(assemblyIdentity); assemblyInfo.Load(assembly); AssemblyList.TryAdd(assemblyIdentity, assemblyInfo); foreach (var assemblySystem in AssemblySystems) { await assemblySystem.Load(assemblyIdentity); } } } /// /// 卸载程序集 /// /// public static async FTask UnLoadAssembly(System.Reflection.Assembly assembly) { var assemblyIdentity = AssemblyIdentity(assembly); if (!AssemblyList.Remove(assemblyIdentity, out var assemblyInfo)) { return; } assemblyInfo.Unload(); foreach (var assemblySystem in AssemblySystems) { await assemblySystem.OnUnLoad(assemblyIdentity); } } /// /// 将AssemblySystem接口的object注册到程序集管理中心 /// /// public static async FTask Register(object obj) { if (obj is not IAssembly assemblySystem) { return; } #if FANTASY_WEBGL AssemblySystems.Add(assemblySystem); #else AssemblySystems.Enqueue(assemblySystem); #endif foreach (var (assemblyIdentity, _) in AssemblyList) { await assemblySystem.Load(assemblyIdentity); } } /// /// 程序集管理中心卸载注册的Load、ReLoad、UnLoad的接口 /// /// public static void UnRegister(object obj) { if (obj is not IAssembly assemblySystem) { return; } #if FANTASY_WEBGL AssemblySystems.Remove(assemblySystem); #else var count = AssemblySystems.Count; for (var i = 0; i < count; i++) { if (!AssemblySystems.TryDequeue(out var removeAssemblySystem)) { continue; } if (removeAssemblySystem == assemblySystem) { break; } AssemblySystems.Enqueue(removeAssemblySystem); } #endif } /// /// 获取所有已加载程序集中的所有类型。 /// /// 所有已加载程序集中的类型。 public static IEnumerable ForEach() { foreach (var (_, assemblyInfo) in AssemblyList) { foreach (var type in assemblyInfo.AssemblyTypeList) { yield return type; } } } /// /// 获取指定程序集中的所有类型。 /// /// 程序集唯一标识。 /// 指定程序集中的类型。 public static IEnumerable ForEach(long assemblyIdentity) { if (!AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo)) { yield break; } foreach (var type in assemblyInfo.AssemblyTypeList) { yield return type; } } /// /// 获取所有已加载程序集中实现指定类型的所有类型。 /// /// 要查找的基类或接口类型。 /// 所有已加载程序集中实现指定类型的类型。 public static IEnumerable ForEach(Type findType) { foreach (var (_, assemblyInfo) in AssemblyList) { if (!assemblyInfo.AssemblyTypeGroupList.TryGetValue(findType, out var assemblyLoad)) { continue; } foreach (var type in assemblyLoad) { yield return type; } } } /// /// 获取指定程序集中实现指定类型的所有类型。 /// /// 程序集唯一标识。 /// 要查找的基类或接口类型。 /// 指定程序集中实现指定类型的类型。 public static IEnumerable ForEach(long assemblyIdentity, Type findType) { if (!AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo)) { yield break; } if (!assemblyInfo.AssemblyTypeGroupList.TryGetValue(findType, out var assemblyLoad)) { yield break; } foreach (var type in assemblyLoad) { yield return type; } } /// /// 获取指定程序集的实例。 /// /// 程序集名称。 /// 指定程序集的实例,如果未加载则返回 null。 public static System.Reflection.Assembly GetAssembly(long assemblyIdentity) { return !AssemblyList.TryGetValue(assemblyIdentity, out var assemblyInfo) ? null : assemblyInfo.Assembly; } /// /// 获取当前框架注册的Assembly /// /// public static IEnumerable ForEachAssembly { get { foreach (var (_, assemblyInfo) in AssemblyList) { yield return assemblyInfo.Assembly; } } } /// /// 根据Assembly的强命名计算唯一标识。 /// /// /// private static long AssemblyIdentity(System.Reflection.Assembly assembly) { return HashCodeHelper.ComputeHash64(assembly.GetName().Name); } /// /// 释放资源,卸载所有加载的程序集。 /// public static void Dispose() { DisposeAsync().Coroutine(); } private static async FTask DisposeAsync() { foreach (var (_, assemblyInfo) in AssemblyList.ToArray()) { await UnLoadAssembly(assemblyInfo.Assembly); } AssemblyList.Clear(); AssemblySystems.Clear(); } } }