Skip to content

Instantly share code, notes, and snippets.

@Zammy
Last active January 31, 2019 09:43
Show Gist options
  • Save Zammy/dcf06b66a36a965fd0b1932d862b8696 to your computer and use it in GitHub Desktop.
Save Zammy/dcf06b66a36a965fd0b1932d862b8696 to your computer and use it in GitHub Desktop.
Service locator pattern in C#
using System;
using System.Collections.Generic;
using System.Linq;
using UniRx;
public interface IService
{
}
public interface IInitializable
{
void Init();
}
public interface ILateInitializable
{
void LateInit();
}
public interface IDestroyable
{
void Destroy();
}
public interface IAppPause
{
void OnAppPause(bool pause);
}
public interface IAppQuit
{
void OnAppQuit();
}
public interface ITickable
{
void Tick(float deltaTime);
}
public interface ITickableUnscaled
{
void TickUnscaled(float deltaTime);
}
public class ServiceLocator : Singleton<ServiceLocator>
{
List<Tuple<int, IService>> _services = new List<Tuple<int, IService>>();
readonly Subject<IService> _onServiceRegisteredSubject = new Subject<IService>();
public IObservable<T> OnServiceRegistered<T>() where T : IService
{
var service = GetService<T>();
if (service != null)
{
return Observable.Return(service);
}
return _onServiceRegisteredSubject
.Where(s => typeof(T).IsAssignableFrom(s.GetType()))
.Select(s => (T)s);
}
public void RegisterService(IService service, int priority = 0)
{
if (_services.Any(t => t.Item2 == service))
{
throw new ArgumentException(service.GetType().Name + " already registered! Unregister previous instance!");
}
_services.Add(new Tuple<int, IService>(priority, service));
_onServiceRegisteredSubject.OnNext(service);
}
public void UnregisterService(IService service)
{
for (int i = 0; i < _services.Count; i++)
{
if (_services[i].Item2 == service)
{
_services.RemoveAt(i);
return;
}
}
}
public void UnregisterService<T>() where T : IService
{
_services.RemoveAll(s => s.Item2 is T);
}
public T GetService<T>()
{
for (int i = 0; i < _services.Count; i++)
{
if (typeof(T).IsAssignableFrom(_services[i].Item2.GetType()))
{
return (T)_services[i].Item2;
}
}
return default(T);
}
public void InitServices()
{
_services = _services.OrderBy(t => t.Item1).ToList();
foreach (var tuple in _services)
{
var service = tuple.Item2 as IInitializable;
if (service != null)
{
service.Init();
}
}
}
public void LateInitServices()
{
foreach (var tuple in _services)
{
var service = tuple.Item2 as ILateInitializable;
if (service != null)
{
service.LateInit();
}
}
}
public void DestroyServices()
{
foreach (var tuple in _services)
{
var service = tuple.Item2 as IDestroyable;
if (service != null)
{
service.Destroy();
}
}
_services.Clear();
}
public void OnAppPauseServices(bool pause)
{
foreach (var tuple in _services)
{
var service = tuple.Item2 as IAppPause;
if (service != null)
{
service.OnAppPause(pause);
}
}
}
public void AppQuitServices()
{
foreach (var tuple in _services)
{
var service = tuple.Item2 as IAppQuit;
if (service != null)
{
service.OnAppQuit();
}
}
UnityEngine.Application.Quit();
}
public void TickServices(float deltaTime, float unscaledDeltaTime)
{
foreach (var tuple in _services)
{
var scaled = tuple.Item2 as ITickable;
if (scaled != null)
{
scaled.Tick(deltaTime);
}
var unscaled = tuple.Item2 as ITickableUnscaled;
if (unscaled != null)
{
unscaled.TickUnscaled(unscaledDeltaTime);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment