using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using UnityEngine; namespace Syntriax.Modules.Movement.Config { public class MovementFactory : MonoBehaviour { private const string Name = "Movement Factory"; private const int InitialCapacity = 64; private static MovementFactory _instance = null; public static MovementFactory Instance { get { if (_instance == null) _instance = new GameObject(Name).AddComponent(); return _instance; } } private Dictionary _types = null; public Dictionary Types { get { if (_types == null) Initialize(); return _types; } } private Func predicate = type => !type.IsAbstract && type.IsSubclassOf(typeof(MonoBehaviour)); private void Start() { if (_instance == this) return; Destroy(this); } public void Initialize() { if (_types == null) _types = new Dictionary(InitialCapacity); Reset(); foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) AddAssemblyToFactory(assembly); } public void Reset() => _types?.Clear(); public void AddAssemblyToFactory(Assembly assembly) { foreach (Type type in assembly.GetTypes().Where(predicate)) Types.Add(GetTypeName(type), type); } public Component AddToGameObject(GameObject gameObject, string name) { if (!Types.ContainsKey(name)) throw new ArgumentException($"The key \"{name}\" does not exists in the current {Name}"); return gameObject.AddComponent(Types[name]); } public static string GetTypeName(Type type) { if (string.IsNullOrEmpty(type.Namespace)) return type.Name; return $"{type.Namespace}.{type.Name}"; } } }