using DigitalData.Core.Abstraction.Application.Repository; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using System.ComponentModel.DataAnnotations.Schema; using System.Reflection; namespace DigitalData.Core.Infrastructure; public static class DependencyInjection { public static IServiceCollection AddDbRepository(this IServiceCollection services, Action options) { var cfg = new RepositoryConfiguration(); options.Invoke(cfg); // 1. FromAssembly cfg.RegsFromAssembly.InvokeAll(services); // 2. Entities to be able overwrite cfg.RegsEntity.InvokeAll(services); return services; } public class RepositoryConfiguration { // 1. register from assembly internal Queue> RegsFromAssembly = new(); // 2. register entities (can overwrite) internal Queue> RegsEntity = new(); internal RepositoryConfiguration() { } public RepositoryConfiguration RegisterFromAssembly(Assembly assembly) where TDbContext : DbContext { void reg(IServiceCollection services) { // scan all types in the Assembly var entityTypes = assembly.GetTypes() .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute() != null); foreach (var entityType in entityTypes) { // create generic DbRepository type var repositoryType = typeof(DbRepository<,>).MakeGenericType(typeof(TDbContext), entityType); var interfaceType = typeof(IRepository<>).MakeGenericType(entityType); // add into DI container as Scoped services.AddScoped(interfaceType, repositoryType); } } RegsFromAssembly.Enqueue(reg); return this; } public RepositoryConfiguration RegisterEntity() where TDbContext : DbContext where TEntity : class { static void reg(IServiceCollection services) => services.AddScoped, DbRepository>(); RegsEntity.Enqueue(reg); return this; } } private static void InvokeAll(this Queue> queue, T services) { while (queue.Count > 0) queue.Dequeue().Invoke(services); } }