I made this service locator to be used on my game projects, but it uses pure c#. Basically, new services needs to inherit from the common IService interface to be registered. I also added events to provide the services so that you cannot run into initialization timing null errors, and the dictionaries use string as keys to use less memory than System.Type
using System;
using System.Collections.Generic;
namespace Game.ServiceLocator
{
public static class GameServiceLocator
{
private static readonly Dictionary<string, IService> _gameServices = new Dictionary<string, IService>();
private static readonly Dictionary<string, Delegate> _serviceAvailabilityCallbacks = new Dictionary<string, Delegate>();
public static void RegisterGameService<T>(T service) where T : IService
{
string serviceName = typeof(T).Name;
if (_gameServices.ContainsKey(serviceName))
{
_gameServices[serviceName] = service;
}
else
{
_gameServices.Add(serviceName, service);
}
NotifyUsersAboutServiceAvailability(serviceName, service);
}
public static void DeRegisterGameService<T>() where T : IService
{
string serviceName = typeof(T).Name;
if (_gameServices.ContainsKey(serviceName))
{
_gameServices.Remove(serviceName);
}
}
public static void GetGameServiceWhenAvailable<T>(Action<IService> listener) where T : IService
{
string serviceName = typeof(T).Name;
AddServiceAvailabilityCallbackListener(serviceName, listener);
if (_gameServices.TryGetValue(serviceName, out IService service))
{
listener.Invoke(service);
return;
}
}
public static void RemoveServiceListenerCallback<T>(Action<IService> listener) where T : IService
{
string serviceName = typeof(T).Name;
if (_serviceAvailabilityCallbacks.TryGetValue(serviceName, out Delegate value))
{
_serviceAvailabilityCallbacks[serviceName] = Delegate.Remove(value, listener);
return;
}
}
private static void AddServiceAvailabilityCallbackListener(string serviceName, Action<IService> listener)
{
if (_serviceAvailabilityCallbacks.TryGetValue(serviceName, out Delegate value))
{
_serviceAvailabilityCallbacks[serviceName] = Delegate.Combine(value, listener);
return;
}
_serviceAvailabilityCallbacks.Add(serviceName, listener);
}
private static void NotifyUsersAboutServiceAvailability(string serviceName, IService service)
{
if (_serviceAvailabilityCallbacks.TryGetValue(serviceName, out Delegate serviceAvailabilityCallback))
{
serviceAvailabilityCallback?.DynamicInvoke(service);
}
}
}
}
//this is in another file
namespace Game.ServiceLocator
{
public interface IService
{
}
}