using System; using System.Collections.Generic; using System.Threading; using Cysharp.Threading.Tasks; using UnityEngine; namespace RebootKit.Engine.Foundation { public interface IService : IDisposable { UniTask OnInit(CancellationToken cancellationToken); } public abstract class ServiceMonoBehaviour : MonoBehaviour, IService { public abstract UniTask OnInit(CancellationToken cancellationToken); public abstract void Dispose(); } public abstract class ServiceAsset : ScriptableObject where T : IService { public abstract T Create(); } public abstract class ServiceAsset : ServiceAsset { } public class ServicesLocator { private static readonly Logger _logger = new(nameof(ServicesLocator)); private static ServicesLocator _shared; public static ServicesLocator Shared { get { if (_shared == null) { _shared = new ServicesLocator(); } return _shared; } } private readonly Dictionary _servicesMap = new(); public void Register(IService service, Type type) { if (!_servicesMap.TryAdd(type, service)) { _logger.Error($"There is already game service of type `{type}`"); return; } service.OnInit(default); _logger.Info($"Registered service of type {type.Name}"); } public void Register(T service) where T : IService { Register(service, service.GetType()); } public async UniTask RegisterAsync(T service, CancellationToken cancellationToken = default) where T : IService { if (!_servicesMap.TryAdd(typeof(T), service)) { _logger.Error($"There is already game service of type `{typeof(T).Name}`"); return; } await service.OnInit(cancellationToken); _logger.Info($"Registered service of type {typeof(T).Name}"); } public void UnRegister(Type type) { if (_servicesMap.TryGetValue(type, out IService service)) { service.Dispose(); _servicesMap.Remove(type); _logger.Info($"Unregistered service of type {type.Name}"); } } public void UnRegisterAll() { foreach (IService service in _servicesMap.Values) { service.Dispose(); } _servicesMap.Clear(); } public IService Get(Type type) { if (_servicesMap.TryGetValue(type, out IService service)) { return service; } Debug.LogAssertionFormat($"Couldn't find service of type `{type}`"); return null; } public T Get() where T : IService { return (T) Get(typeof(T)); } } }