refactor(dependency-injection): replace generic AddDbRepository with configurable registration
- Replaced `AddDbRepository<TDbContext, TEntity>` with `AddDbRepository(Action<RepositoryConfiguration>)` for more flexible DI registration. - Added `RepositoryConfiguration` class to support: - Registering repositories from an assembly (`RegisterFromAssembly`) - Registering individual entities (`RegisterEntity`) - Queues (`RegsFromAssembly` and `RegsEntity`) are used to defer registration until `InvokeAll` is called. - Allows overriding and scanning multiple entities dynamically instead of static generic method.
This commit is contained in:
parent
84cd52cc45
commit
33f7ced3b2
@ -1,19 +1,74 @@
|
||||
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 EntityConfigurationOptions<TEntity> AddDbRepository<TDbContext, TEntity>(this IServiceCollection services, Func<TDbContext, DbSet<TEntity>> queryFactory)
|
||||
where TDbContext : DbContext
|
||||
where TEntity : class
|
||||
public static IServiceCollection AddDbRepository(this IServiceCollection services, Action<RepositoryConfiguration> options)
|
||||
{
|
||||
services
|
||||
.AddScoped<IRepository<TEntity>, DbRepository<TDbContext, TEntity>>()
|
||||
.AddSingleton(queryFactory);
|
||||
var cfg = new RepositoryConfiguration();
|
||||
options.Invoke(cfg);
|
||||
|
||||
return new EntityConfigurationOptions<TEntity>(services);
|
||||
// 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<Action<IServiceCollection>> RegsFromAssembly = new();
|
||||
|
||||
// 2. register entities (can overwrite)
|
||||
internal Queue<Action<IServiceCollection>> RegsEntity = new();
|
||||
|
||||
internal RepositoryConfiguration() { }
|
||||
|
||||
public RepositoryConfiguration RegisterFromAssembly<TDbContext>(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<TableAttribute>() != null);
|
||||
|
||||
foreach (var entityType in entityTypes)
|
||||
{
|
||||
// create generic DbRepository<DbContext, TEntity> 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<TDbContext, TEntity>() where TDbContext : DbContext
|
||||
where TEntity : class
|
||||
{
|
||||
static void reg(IServiceCollection services)
|
||||
=> services.AddScoped<IRepository<TEntity>, DbRepository<TDbContext, TEntity>>();
|
||||
|
||||
RegsEntity.Enqueue(reg);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private static void InvokeAll<T>(this Queue<Action<T>> queue, T services)
|
||||
{
|
||||
while (queue.Count > 0)
|
||||
queue.Dequeue().Invoke(services);
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user