using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using System.Reflection; namespace TheXamlGuy.Framework.Core { public static class IServiceCollectionExtensions { public static IServiceCollection AddConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfiguration : class, new() { serviceCollection.Configure(configuration); serviceCollection.AddTransient(provider => provider.GetService>()!.CurrentValue); serviceCollection.AddTransient>(); return serviceCollection; } public static IServiceCollection AddCreatable(this IServiceCollection services) { return services.AddSingleton(typeof(IServiceCreator<>).MakeGenericType(typeof(TService)), typeof(ServiceCreator<,>).MakeGenericType(typeof(TService), typeof(TImplementation))); } public static IServiceCollection AddCreatable(this IServiceCollection services, Type serviceType, Type implementationType) { return services.AddSingleton(typeof(IServiceCreator<>).MakeGenericType(serviceType), typeof(ServiceCreator<,>).MakeGenericType(serviceType, implementationType)); } public static IServiceCollection AddCreatableSingleton(this IServiceCollection services, Type serviceType, Type implementationType) { services.AddSingleton(serviceType, implementationType); services.AddCreatable(serviceType, implementationType); return services; } public static IServiceCollection AddCreatableTransient(this IServiceCollection services, Type serviceType, Type implementationType) { services.AddTransient(serviceType, implementationType); services.AddCreatable(serviceType, implementationType); return services; } public static IServiceCollection AddReqiredCore(this IServiceCollection services) { return services .AddSingleton(provider => new ServiceFactory(provider.GetService, (type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!))) .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() .AddTransient() .AddTransient() .AddSingleton(provider => new Initialization(() => { return services.Where(x => x.ServiceType.GetInterfaces() .Contains(typeof(IInitializer)) || x.ServiceType == typeof(IInitializer)) .GroupBy(x => x.ServiceType) .Select(x => x.First()) .SelectMany(x => provider.GetServices(x.ServiceType) .Select(x => (IInitializer?)x)).ToList(); })) .RegisterHandlers(); } public static IServiceCollection AddWritableConfiguration(this IServiceCollection serviceCollection, IConfiguration configuration) where TConfiguration : class, new() { serviceCollection.Configure(configuration); serviceCollection.AddTransient, ConfigurationWriter>(); serviceCollection.AddTransient(provider => provider.GetService>()!.CurrentValue); serviceCollection.AddTransient>, WriteHandler>(); serviceCollection.AddTransient>(); return serviceCollection; } public static IServiceCollection RegisterHandlers(this IServiceCollection services, params Assembly[] assemblies) { foreach (Tuple item in GetImplementations(assemblies.Append(Assembly.GetCallingAssembly()), "Handler", typeof(IMediatorHandler<>), typeof(IMediatorHandler<,>), typeof(IMediatorAsyncHandler<>), typeof(IMediatorAsyncHandler<,>))) { if (!item.Item2.GetConstructors().Any(x => x.IsPublic)) { continue; } services.AddCreatableTransient(item.Item1, item.Item2); } return services; } private static IEnumerable> GetImplementations(IEnumerable assemblies, string endsWith, params Type[] interfaces) { return assemblies.Distinct().SelectMany(a => a.GetTypes()) .Where(impl => impl.IsClass && impl.IsPublic && !impl.IsAbstract && impl.Name.EndsWith(endsWith)) .SelectMany(impl => impl.GetInterfaces(), (impl, iface) => new { impl, iface }) .Where(i => i.iface.IsGenericType && interfaces.Contains(i.iface.GetGenericTypeDefinition())) .Select(x => Tuple.Create(x.iface, x.impl)); } } }