using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using zero.Core.Assemblies; namespace zero.Core.Extensions { public static class ServiceCollectionExtensions { /// /// Adds all found implementations based on the service type and assembly discovery rules /// public static void AddAll(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient, bool asSelf = false) => services.AddAll(typeof(TService), lifetime, asSelf); /// /// Adds all found implementations based on the service type and assembly discovery rules /// public static void AddAll(this IServiceCollection services, Type serviceType, ServiceLifetime lifetime = ServiceLifetime.Transient, bool asSelf = false) { if (AssemblyDiscovery.Current == null) { throw new Exception("services.AddAll() can only be run after mvcBuilder.AddZero()"); } // add implementations with generic service types if (serviceType.GetTypeInfo().IsGenericTypeDefinition) { IEnumerable<(Type, TypeInfo)> matches = AssemblyDiscovery.Current.GetAllClassTypes().SelectMany(type => { var interfaces = type.GetInterfaces().Select(x => x.GetTypeInfo()); IEnumerable genericTypes = interfaces.Where(x => x.IsGenericType && x.GetGenericTypeDefinition() == serviceType); if (genericTypes.Any()) { var genericTypeDefinitions = genericTypes.First(); } return genericTypes.Select(x => (x, type)); }); foreach ((Type, Type) match in matches) { services.Add(new ServiceDescriptor(asSelf ? match.Item2 : match.Item1, match.Item2, lifetime)); } } // add implementations with specific service types else { foreach (Type type in AssemblyDiscovery.Current.GetTypes(serviceType)) { services.Add(new ServiceDescriptor(asSelf ? type : serviceType, type, lifetime)); } } } /// /// Adds or overrides an implementation /// public static void Replace(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient) where TService : class where TImplementation : class, TService { services.RemoveAll(); services.Add(new ServiceDescriptor(typeof(TService), typeof(TImplementation), lifetime)); } /// /// Adds or overrides an implementation /// public static void Replace(this IServiceCollection services, Func implementationFactory, ServiceLifetime lifetime = ServiceLifetime.Transient) where TService : class where TImplementation : class, TService { services.RemoveAll(); services.Add(new ServiceDescriptor(typeof(TService), implementationFactory, lifetime)); } } }