using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; namespace Toolkit.Foundation; public static class IServiceCollectionExtensions { public static IServiceCollection AddCache(this IServiceCollection services) where TKey : notnull where TValue : notnull { services.AddScoped, Cache>(); services.AddTransient(provider => provider.GetService>()!.Select(x => x.Value)); return services; } public static IServiceCollection AddCache(this IServiceCollection services) { services.AddSingleton, Cache>(); services.AddTransient(provider => provider.GetService>()!.Select(x => x)); return services; } public static IServiceCollection AddComponent(this IServiceCollection services) where TComponent : class, IComponent { services.AddTransient(); return services; } public static IServiceCollection AddHandler(this IServiceCollection services, string key) where THandler : IHandler { return AddHandler(services, ServiceLifetime.Transient, key); } public static IServiceCollection AddHandler(this IServiceCollection services, ServiceLifetime lifetime = ServiceLifetime.Transient, string? key = null) where THandler : IHandler { if (typeof(THandler).GetInterfaces() is Type[] contracts) { foreach (Type contract in contracts) { if (contract.Name == typeof(INotificationHandler<>).Name && contract.GetGenericArguments() is { Length: 1 } notificationHandlerArguments) { Type notificationType = notificationHandlerArguments[0]; Type wrapperType = typeof(NotificationHandlerWrapper<>) .MakeGenericType(notificationType); if (key is not null) { services.TryAdd(new ServiceDescriptor(typeof(INotificationHandler<>) .MakeGenericType(notificationType), key, typeof(THandler), lifetime)); } else { services.TryAdd(new ServiceDescriptor(typeof(INotificationHandler<>) .MakeGenericType(notificationType), typeof(THandler), lifetime)); } if (key is not null) { services.Add(new ServiceDescriptor(wrapperType, key, (provider, key) => provider.GetService()?.Create(wrapperType, provider.GetRequiredKeyedService(typeof(INotificationHandler<>).MakeGenericType(notificationType), key), provider.GetServices(typeof(IPipelineBehaviour<>) .MakeGenericType(notificationType)))!, lifetime)); } else { services.Add(new ServiceDescriptor(wrapperType, provider => provider.GetService()?.Create(wrapperType, provider.GetRequiredService(typeof(INotificationHandler<>).MakeGenericType(notificationType)), provider.GetServices(typeof(IPipelineBehaviour<>) .MakeGenericType(notificationType)))!, lifetime)); } } if (contract.Name == typeof(IHandler<,>).Name && contract.GetGenericArguments() is { Length: 2 } handlerArguments) { Type requestType = handlerArguments[0]; Type responseType = handlerArguments[1]; Type wrapperType = typeof(HandlerWrapper<,>) .MakeGenericType(requestType, responseType); services.TryAdd(new ServiceDescriptor(typeof(THandler), typeof(THandler), lifetime)); services.Add(new ServiceDescriptor(wrapperType, provider => provider.GetService()?.Create(wrapperType, provider.GetRequiredService(), provider.GetServices(typeof(IPipelineBehaviour<,>) .MakeGenericType(requestType, responseType)))!, lifetime)); } } return services; } return services; } public static IServiceCollection AddInitializer(this IServiceCollection services) where TInitializer : class, IInitializer { services.AddTransient(); return services; } public static IServiceCollection AddNavigateHandler(this IServiceCollection services) where THandler : INavigateHandler, IHandler { IEnumerable contracts = typeof(THandler).GetInterfaces() .Where(x => x.Name == typeof(INavigateHandler<>).Name || x.Name == typeof(INavigateBackHandler<>).Name); foreach (Type contract in contracts) { if (contract.GetGenericArguments() is { Length: 1 } arguments) { services.AddTransient(provider => new Navigation { Type = arguments[0] }); } } services.AddHandler(); return services; } public static IServiceCollection AddRange(this IServiceCollection services, IServiceCollection fromServices) { foreach (ServiceDescriptor service in fromServices) { services.Add(service); } return services; } public static IServiceCollection AddTemplate(this IServiceCollection services, object? key = null, ServiceLifetime serviceLifetime = ServiceLifetime.Transient, params object[]? parameters) { Type viewModelType = typeof(TViewModel); Type viewType = typeof(TView); key ??= viewModelType.Name.Replace("ViewModel", ""); if (parameters is { Length: 0 }) { services.Add(new ServiceDescriptor(viewModelType, viewModelType, serviceLifetime)); } else { services.Add(new ServiceDescriptor(viewModelType, provider => provider.GetRequiredService().Create(parameters)!, serviceLifetime)); } services.Add(new ServiceDescriptor(viewType, viewType, serviceLifetime)); if (parameters is { Length: 0 }) { services.Add(new ServiceDescriptor(viewModelType, key, viewModelType, serviceLifetime)); } else { services.Add(new ServiceDescriptor(viewModelType, key, (provider, key) => provider.GetRequiredService().Create(parameters)!, serviceLifetime)); } services.Add(new ServiceDescriptor(viewType, key, viewType, serviceLifetime)); services.AddTransient(provider => new ContentTemplateDescriptor(key, viewModelType, viewType, parameters)); return services; } }