Files

55 lines
2.3 KiB
C#
Raw Permalink Normal View History

using System;
using System.Collections.Generic;
// Реестр модулей: модуль регистрирует свой контракт, остальные получают его отсюда.
// Так модули не ссылаются на классы друг друга: Армия знает про IEconomy, но не про ResourceManager.
//
// GameServices.Register<IEconomy>(this); // в модуле Экономики
// GameServices.Get<IEconomy>().TrySpend(ResourceType.Food, 15); // в любом другом модуле
public static class GameServices
{
private static readonly Dictionary<Type, object> services = new Dictionary<Type, object>();
public static void Register<T>(T service) where T : class
{
services[typeof(T)] = service ?? throw new ArgumentNullException(nameof(service));
}
// Снимает регистрацию, только если зарегистрирован именно этот экземпляр
// (дубликат синглтона, уничтожаясь, не должен снять настоящий)
public static void Unregister<T>(T service) where T : class
{
if (services.TryGetValue(typeof(T), out object current) && ReferenceEquals(current, service))
services.Remove(typeof(T));
}
public static T Get<T>() where T : class
{
if (services.TryGetValue(typeof(T), out object service)) return (T)service;
throw new InvalidOperationException(
$"Модуль {typeof(T).Name} не зарегистрирован. Проверь, что он есть на сцене или в App/GameModules.");
}
public static bool TryGet<T>(out T service) where T : class
{
if (services.TryGetValue(typeof(T), out object found))
{
service = (T)found;
return true;
}
service = null;
return false;
}
public static bool Has<T>() where T : class
{
return services.ContainsKey(typeof(T));
}
// Полная очистка -- при старте игры (в редакторе статика может пережить прошлый запуск)
public static void Clear()
{
services.Clear();
}
}