using System; using System.Collections.Generic; using System.Linq; using UnityEngine; namespace PMaker.DependencyInjection { public static class IoC { private static IoCContainer _container = new IoCContainer(); [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)] static void Init() { _container = new IoCContainer(); #if UNITY_EDITOR var obj = new GameObject("IoCContainer"); obj.AddComponent().container = _container; GameObject.DontDestroyOnLoad(obj); #endif } #region singleton public static void AddSingleton(T instance) where T : class { _container.AddSingleton(instance); } public static void AddSingleton(Type type, object instance) { _container.AddSingleton(type, instance); } public static void RemoveSingleton() where T : class { _container.RemoveSingleton(); } public static void RemoveSingleton(Type type) { _container.RemoveSingleton(type); } public static T GetSingleton() where T : class { return _container.GetSingleton(); } public static void ClearSingleton() { _container.ClearSingletons(); } #endregion #region instance public static void AddInstance(T instance) where T : class { _container.AddInstance(instance); } public static void RemoveInstance(T instance) where T : class { _container.RemoveInstance(instance); } public static void RemoveInstance(Type type, object instance) { _container.RemoveInstance(type, instance); } public static void RemoveInstances() where T : class { _container.RemoveInstances(); } public static void RemoveInstances(Type type) { _container.RemoveInstances(type); } public static IEnumerable GetInstance() where T : class { return _container.GetInstances(); } public static void ClearAllInstances() { _container.ClearAllInstances(); } #endregion public static bool TryGetSingleton(out T instance) where T : class { instance = _container.GetSingleton(); return instance != null; } } public interface ISingletonCollection { void AddSingleton(T instance) where T : class; void AddSingleton(Type type, object instance); void RemoveSingleton() where T : class; void RemoveSingleton(Type type); void ClearSingletons(); T GetSingleton() where T : class; } public interface IInstanceCollection { void AddInstance(T instance) where T : class; void AddInstance(Type type, object instance); void RemoveInstance(T instance) where T : class; void RemoveInstance(Type type, object instance); void RemoveInstances() where T : class; void RemoveInstances(Type type); void ClearAllInstances(); IEnumerable GetInstances() where T : class; } public partial class IoCContainer : ISingletonCollection, IInstanceCollection { private Dictionary _singletonMapper; private Dictionary> _instanceMapper; public IoCContainer() { this._singletonMapper = new Dictionary(); this._instanceMapper = new Dictionary>(); } #region singleton public void RemoveSingleton(Type type) { this._singletonMapper.Remove(type); } public void AddSingleton(Type type, object instance) { this._singletonMapper.Add(type, instance); } public void AddSingleton(T instance) where T : class { this._singletonMapper.Add(typeof(T), instance); } public void RemoveSingleton() where T : class { this._singletonMapper.Remove(typeof(T)); } public T GetSingleton() where T : class { this._singletonMapper.TryGetValue(typeof(T), out var instance); return instance as T; } public void ClearSingletons() { this._singletonMapper.Clear(); } #endregion #region instance public void AddInstance(T instance) where T : class { var type = instance.GetType(); if (this._instanceMapper.TryGetValue(type, out var set)) { set.Add(instance); } else { this._instanceMapper.Add(type, new HashSet() { instance }); } } public void AddInstance(Type type, object instance) { if (this._instanceMapper.TryGetValue(type, out var set)) { set.Add(instance); } else { this._instanceMapper.Add(type, new HashSet() { instance }); } } public void RemoveInstance(T instance) where T : class { this.RemoveInstance(typeof(T), instance); } public void RemoveInstance(Type type, object instance) { if (this._instanceMapper.TryGetValue(type, out var set)) { set.Remove(instance); } else { } } public IEnumerable GetInstances() where T : class { var type = typeof(T); if (this._instanceMapper.TryGetValue(type, out var set)) { return set.Select(_ => _ as T); } return null; } public void RemoveInstances() where T : class { var type = typeof(T); if (this._instanceMapper.TryGetValue(type, out var set)) { set.Clear(); } } public void RemoveInstances(Type type) { if (this._instanceMapper.TryGetValue(type, out var set)) { set.Clear(); } } public void ClearAllInstances() { this._instanceMapper.Clear(); } #endregion } #if UNITY_EDITOR public partial class IoCContainer { public class Mono : BaseBehaviour { [SerializeField] [Sirenix.OdinInspector.ReadOnly] public Dictionary SingletonMapper { get => container._singletonMapper; set => container._singletonMapper = value; } [SerializeField] [Sirenix.OdinInspector.ReadOnly] public Dictionary> InstanceMapper { get => container._instanceMapper; set => container._instanceMapper = value; } public IoCContainer container; } } #endif }