From c3d47f6b38ab4888a1d5935182db723e6e8bb39e Mon Sep 17 00:00:00 2001 From: Chris Cameron Date: Mon, 2 Oct 2017 14:57:13 -0400 Subject: [PATCH] Tidying, validation, prevent ServiceProvider from being instantiated externally --- ICD.Common.Utils/Services/ServiceProvider.cs | 149 ++++++++++++++----- 1 file changed, 108 insertions(+), 41 deletions(-) diff --git a/ICD.Common.Utils/Services/ServiceProvider.cs b/ICD.Common.Utils/Services/ServiceProvider.cs index 5eac93c..6ba2507 100644 --- a/ICD.Common.Utils/Services/ServiceProvider.cs +++ b/ICD.Common.Utils/Services/ServiceProvider.cs @@ -8,12 +8,60 @@ namespace ICD.Common.Services { public sealed class ServiceProvider : IDisposable { - #region Static - private static ServiceProvider s_Instance; + private readonly Dictionary m_Services; + private readonly SafeCriticalSection m_ServicesSection; + private static ServiceProvider Instance { get { return s_Instance ?? (s_Instance = new ServiceProvider()); } } + /// + /// Prevent external instantiation. + /// + private ServiceProvider() + { + m_Services = new Dictionary(); + m_ServicesSection = new SafeCriticalSection(); + } + + #region IDisposable + + /// + /// Release resources. + /// + 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(); + } + } + + /// + /// Release resources. + /// + public static void DisposeStatic() + { + if (s_Instance != null) + s_Instance.Dispose(); + s_Instance = null; + } + + #endregion + + #region Methods + /// /// Retrieves the registered service of the given type. Use this for required dependencies. /// @@ -37,6 +85,9 @@ namespace ICD.Common.Services [NotNull] public static object GetService(Type tService) { + if (tService == null) + throw new ArgumentNullException("tService"); + return Instance.GetServiceInstance(tService); } @@ -63,14 +114,10 @@ namespace ICD.Common.Services [CanBeNull] public static object TryGetService(Type tService) { - try - { - return Instance.GetServiceInstance(tService); - } - catch (ServiceNotFoundException) - { - return null; - } + if (tService == null) + throw new ArgumentNullException("tService"); + + return Instance.TryGetServiceInstance(tService); } /// @@ -81,6 +128,10 @@ namespace ICD.Common.Services [PublicAPI] public static void AddService(TService service) { +// ReSharper disable once CompareNonConstrainedGenericWithNull + if (service == null) + throw new ArgumentNullException("service"); + AddService(typeof(TService), service); } @@ -92,26 +143,38 @@ namespace ICD.Common.Services [PublicAPI] public static void AddService(Type tService, object service) { + if (tService == null) + throw new ArgumentNullException("tService"); + + if (service == null) + throw new ArgumentNullException("service"); + Instance.AddServiceInstance(tService, service); } #endregion - private readonly Dictionary m_Services = new Dictionary(); - private readonly SafeCriticalSection m_ServicesSection = new SafeCriticalSection(); + #region Private Methods - #region Methods - - private object GetServiceInstance(Type 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 + [CanBeNull] + private object TryGetServiceInstance(Type tService) { + if (tService == null) + throw new ArgumentNullException("tService"); + try { m_ServicesSection.Enter(); object service; - if (m_Services.TryGetValue(tService, out service) && service != null) - return service; - throw new ServiceNotFoundException(tService); + m_Services.TryGetValue(tService, out service); + return service; } finally { @@ -119,30 +182,41 @@ namespace ICD.Common.Services } } + /// + /// Gets the service of the given type. + /// + /// + /// + private object GetServiceInstance(Type tService) + { + if (tService == null) + throw new ArgumentNullException("tService"); + + object service = TryGetService(tService); + if (service != null) + return service; + + throw new ServiceNotFoundException(tService); + } + + /// + /// Adds the given service under the given type. + /// + /// + /// [PublicAPI] private void AddServiceInstance(Type tService, object service) { - m_ServicesSection.Enter(); - m_Services[tService] = service; - m_ServicesSection.Leave(); - } + if (tService == null) + throw new ArgumentNullException("tService"); - #endregion + if (service == null) + throw new ArgumentNullException("service"); - #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(); + m_Services.Add(tService, service); } finally { @@ -150,13 +224,6 @@ namespace ICD.Common.Services } } - public static void DisposeStatic() - { - if (s_Instance != null) - s_Instance.Dispose(); - s_Instance = null; - } - #endregion } }