50 lines
2.0 KiB
C#
50 lines
2.0 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using UnityEngine;
|
||
|
||
namespace BaseGames.Core
|
||
{
|
||
/// <summary>
|
||
/// 轻量服务定位器。通过类型键注册/查找服务,支持接口类型注册(依赖倒置)。
|
||
/// </summary>
|
||
public static class ServiceLocator
|
||
{
|
||
private static readonly Dictionary<Type, object> _services = new();
|
||
|
||
/// <summary>以接口类型 TInterface 注册实现 impl。</summary>
|
||
public static void Register<TInterface>(TInterface impl)
|
||
=> _services[typeof(TInterface)] = impl;
|
||
|
||
/// <summary>仅当尚未注册时才注册(防多场景重复注册同一服务)。</summary>
|
||
public static void RegisterIfAbsent<TInterface>(TInterface impl)
|
||
{
|
||
if (!_services.ContainsKey(typeof(TInterface)))
|
||
_services[typeof(TInterface)] = impl;
|
||
}
|
||
|
||
/// <summary>查找服务。未注册时抛出 InvalidOperationException。</summary>
|
||
public static TInterface Get<TInterface>()
|
||
{
|
||
if (_services.TryGetValue(typeof(TInterface), out var svc) && svc is TInterface typed)
|
||
return typed;
|
||
throw new InvalidOperationException(
|
||
$"[ServiceLocator] Service '{typeof(TInterface).Name}' is not registered. "
|
||
+ "Ensure GameServiceRegistrar.Awake() has run before this call.");
|
||
}
|
||
|
||
/// <summary>安全版 Get:未注册时返回 fallback,不报错(适用于可选服务)。</summary>
|
||
public static TInterface GetOrDefault<TInterface>(TInterface fallback = default)
|
||
=> _services.TryGetValue(typeof(TInterface), out var svc) && svc is TInterface typed
|
||
? typed : fallback;
|
||
|
||
#if UNITY_EDITOR
|
||
/// <summary>单元测试中替换服务实现。</summary>
|
||
public static void OverrideForTest<TInterface>(TInterface mock)
|
||
=> _services[typeof(TInterface)] = mock;
|
||
|
||
/// <summary>清空所有注册(测试用)。</summary>
|
||
public static void Reset() => _services.Clear();
|
||
#endif
|
||
}
|
||
}
|