using Microsoft.Extensions.DependencyInjection; using System.Collections; #if NETFRAMEWORK using System; using System.Collections.Generic; #endif namespace DigitalData.Core.Abstractions { public class Factory : IServiceProvider, IServiceCollection { public static readonly Factory Shared = new Factory(); private readonly IServiceCollection _serviceCollection = new ServiceCollection(); private readonly Lazy _lazyServiceProvider; private bool IsBuilt => _lazyServiceProvider.IsValueCreated; private PostBuildBehavior _pbBehavior = PostBuildBehavior.ThrowException; public Factory BehaveOnPostBuild(PostBuildBehavior postBuildBehavior) { _pbBehavior = postBuildBehavior; return this; } public Factory() { _lazyServiceProvider = new Lazy(() => _serviceCollection.BuildServiceProvider()); } #region Service Provider public object #if NET ? #endif GetService(Type serviceType) { return _lazyServiceProvider.Value.GetService(serviceType); } public IServiceScopeFactory ScopeFactory => this.GetRequiredService(); #endregion #region Service Collection public int Count => _serviceCollection.Count; public bool IsReadOnly => _serviceCollection.IsReadOnly; public ServiceDescriptor this[int index] { get => _serviceCollection[index]; set { if (EnsureBuilt()) return; _serviceCollection[index] = value; } } public int IndexOf(ServiceDescriptor item) { return _serviceCollection.IndexOf(item); } public void Insert(int index, ServiceDescriptor item) { if (EnsureBuilt()) return; _serviceCollection.Insert(index, item); } public void RemoveAt(int index) { if (EnsureBuilt()) return; _serviceCollection.RemoveAt(index); } public void Add(ServiceDescriptor item) { if (EnsureBuilt()) return; _serviceCollection.Add(item); } public void Clear() { if (EnsureBuilt()) return; _serviceCollection.Clear(); } public bool Contains(ServiceDescriptor item) { return _serviceCollection.Contains(item); } public void CopyTo(ServiceDescriptor[] array, int arrayIndex) { _serviceCollection.CopyTo(array, arrayIndex); } public bool Remove(ServiceDescriptor item) { if (EnsureBuilt()) return false; return _serviceCollection.Remove(item); } public IEnumerator GetEnumerator() { return _serviceCollection.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return (_serviceCollection as IEnumerable).GetEnumerator(); } #endregion #region Helpers private bool EnsureBuilt() { if (IsBuilt) { return _pbBehavior == PostBuildBehavior.ThrowException ? throw new InvalidOperationException("Service provider has already been built. No further service modifications are allowed.") : true; } else return false; } #endregion } public enum PostBuildBehavior { ThrowException, Ignore } }