using System; using System.Collections.Generic; using System.Linq; using Monad; public static class ServiceLocator { static readonly List<(string Id, Type ServiceContract, object ServiceImpl)> serviceContainer = new List<(string, Type, object)>(); private static Try BindWithId(string id, TImplementation t) where TContract : class where TImplementation : TContract { if (serviceContainer.Any(item => item.Id.Equals(id))) { return () => throw new Exception("-->[ServiceLocator] the id : ({id}) is registered, please try with new id"); } serviceContainer.Add((id, typeof(TContract), t)); return () => t; } private static Try GetById(string id) where TContract : class { var service = serviceContainer.FirstOrDefault(item => item.Id.Equals(id) && item.ServiceContract == typeof(TContract)); if (service != default) return () => service.ServiceImpl as TContract; if (serviceContainer.All(item => !item.Id.Equals(id))) { return () => throw new Exception($"-->NOT FOUND: [ServiceLocator] not found any service with id : {id}"); } service = serviceContainer.FirstOrDefault(item => item.Id.Equals(id)); return () => throw new Exception( $"-->NOT FOUND: [ServiceLocator] The id: ({id}) exist but the registered type is: [{service.ServiceContract}] NOT [{typeof(TContract)}]"); } public static Try Bind(TImplementation t) where TContract : class where TImplementation : TContract { return BindWithId(typeof(TContract).Name, t); } public static Try Get() where TContract : class { return GetById(typeof(TContract).Name); } }