using System; using System.Linq; using System.Reflection; using Microsoft.Extensions.DependencyInjection; namespace ZhonTai.Tools.DynamicApi.Helpers { internal static class ServiceCollectionExtensions { public static bool IsAdded(this IServiceCollection services) { return services.IsAdded(typeof(T)); } public static bool IsAdded(this IServiceCollection services, Type type) { return services.Any(d => d.ServiceType == type); } public static T GetSingletonInstanceOrNull(this IServiceCollection services) { return (T)services .FirstOrDefault(d => d.ServiceType == typeof(T)) ?.ImplementationInstance; } public static T GetSingletonInstance(this IServiceCollection services) { var service = services.GetSingletonInstanceOrNull(); if (service == null) { throw new InvalidOperationException("Could not find singleton service: " + typeof(T).AssemblyQualifiedName); } return service; } public static IServiceProvider BuildServiceProviderFromFactory(this IServiceCollection services) { foreach (var service in services) { var factoryInterface = service.ImplementationInstance?.GetType() .GetTypeInfo() .GetInterfaces() .FirstOrDefault(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition() == typeof(IServiceProviderFactory<>)); if (factoryInterface == null) { continue; } var containerBuilderType = factoryInterface.GenericTypeArguments[0]; return (IServiceProvider)typeof(ServiceCollectionExtensions) .GetTypeInfo() .GetMethods() .Single(m => m.Name == nameof(BuildServiceProviderFromFactory) && m.IsGenericMethod) .MakeGenericMethod(containerBuilderType) .Invoke(null, new object[] { services, null }); } return services.BuildServiceProvider(); } public static IServiceProvider BuildServiceProviderFromFactory(this IServiceCollection services, Action builderAction = null) { var serviceProviderFactory = services.GetSingletonInstanceOrNull>(); if (serviceProviderFactory == null) { throw new Exception($"Could not find {typeof(IServiceProviderFactory).FullName} in {services}."); } var builder = serviceProviderFactory.CreateBuilder(services); builderAction?.Invoke(builder); return serviceProviderFactory.CreateServiceProvider(builder); } } }