using System; using System.Collections.Generic; using System.Linq; using ICD.Common.Properties; using ICD.Common.Utils; namespace ICD.Common.Services { public sealed class ServiceProvider : IDisposable { #region Static private static ServiceProvider s_Instance; private static ServiceProvider Instance { get { return s_Instance ?? (s_Instance = new ServiceProvider()); } } /// /// Retrieves the registered service of the given type. Use this for required dependencies. /// /// service type to retrieve /// /// Thrown if a service of the given type is not registered [PublicAPI] [NotNull] public static TService GetService() { return (TService)GetService(typeof(TService)); } /// /// Retrieves the registered service of the given type. Use this for required dependencies. /// /// service type to retrieve /// /// Thrown if a service of the given type is not registered [PublicAPI] [NotNull] public static object GetService(Type tService) { return Instance.GetServiceInstance(tService); } /// /// Retrieves the registered service of the given type. Returns null if the service type was not found. /// Use this for optional dependencies. /// /// service type to retrieve /// requested service or null if that service type is not registered [PublicAPI] [CanBeNull] public static TService TryGetService() { return (TService)TryGetService(typeof(TService)); } /// /// Retrieves the registered service of the given type. Returns null if the service type was not found. /// Use this for optional dependencies. /// /// service type to retrieve /// requested service or null if that service type is not registered [PublicAPI] [CanBeNull] public static object TryGetService(Type tService) { try { return Instance.GetServiceInstance(tService); } catch (ServiceNotFoundException) { return null; } } /// /// Registers a service instance to the type given. /// /// /// [PublicAPI] public static void AddService(TService service) { AddService(typeof(TService), service); } /// /// Registers a service instance to the type given. /// /// /// [PublicAPI] public static void AddService(Type tService, object service) { Instance.AddServiceInstance(tService, service); } #endregion private readonly Dictionary m_Services = new Dictionary(); private readonly SafeCriticalSection m_ServicesSection = new SafeCriticalSection(); #region Methods private object GetServiceInstance(Type tService) { try { m_ServicesSection.Enter(); object service; if (m_Services.TryGetValue(tService, out service) && service != null) return service; throw new ServiceNotFoundException(tService); } finally { m_ServicesSection.Leave(); } } [PublicAPI] private void AddServiceInstance(Type tService, object service) { m_ServicesSection.Enter(); m_Services[tService] = service; m_ServicesSection.Leave(); } #endregion #region IDisposable public void Dispose() { try { m_ServicesSection.Enter(); foreach (object service in m_Services.Values.Distinct()) { if (!(service is IDisposable)) continue; ((IDisposable)service).Dispose(); } m_Services.Clear(); } finally { m_ServicesSection.Leave(); } } public static void DisposeStatic() { if (s_Instance != null) s_Instance.Dispose(); s_Instance = null; } #endregion } }