using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; namespace Syntriax.Engine.Core.Factory; public static class TypeFactory { private static readonly ConcurrentDictionary registeredTypes = []; public static string GetTypeName(Type type) => type.FullName ?? throw new ArgumentException($"{type.Name} must be a resolvable type"); public static T Get(params object?[]? args) where T : class => (T)Get(typeof(T), args); public static object Get(string fullName, params object?[]? args) => Get(GetType(fullName), args); public static object Get(Type type, params object?[]? args) { object? result; if (args is not null && args.Length != 0) result = Activator.CreateInstance(type, args); else result = Activator.CreateInstance(type); if (result is null) throw new Exception($"Type {type.Name} could not be created."); return result; } public static Type GetType(string fullName) { if (registeredTypes.TryGetValue(fullName, out Type? result)) return result; ReloadTypes(); if (registeredTypes.TryGetValue(fullName, out Type? reloadedType)) return reloadedType; throw new Exception($"Type {fullName} could not be found in the current domain."); } public static void ReloadTypes() { registeredTypes.Clear(); IEnumerable domainTypes = AppDomain.CurrentDomain .GetAssemblies() .SelectMany(a => a.GetTypes()); // TODO: Replace this // There are some system & compiler generated types with duplicated names, // it is ugly it will cause headaches in the future because it will not // throw an error if there's a type with an unintended duplicate name foreach (Type type in domainTypes) registeredTypes.TryAdd(GetTypeName(type), type); } }