Refactor DependencyInjection and RepositoryConfiguration classes

Restructure code for improved readability and maintainability. Move RepositoryConfiguration as a nested public class inside DependencyInjection, group related service registration logic, and clarify method organization. No functional changes.
This commit is contained in:
2025-12-19 10:09:04 +01:00
parent daa36d767d
commit 1e3cba6fdf

View File

@@ -11,142 +11,134 @@ using System.Linq;
#endif #endif
namespace DigitalData.Core.Infrastructure namespace DigitalData.Core.Infrastructure
#if NET
;
#elif NETFRAMEWORK
{
#endif
public static class DependencyInjection
{ {
public static IServiceCollection AddDbRepository(this IServiceCollection services, Action<RepositoryConfiguration> options) public static class DependencyInjection
{ {
// register services from configuration public static IServiceCollection AddDbRepository(this IServiceCollection services, Action<RepositoryConfiguration> options)
var cfg = new RepositoryConfiguration();
options.Invoke(cfg);
cfg.RegisterAllServices(services);
return services;
}
public class RepositoryConfiguration
{
// 1. register from assembly
private readonly Queue<Action<IServiceCollection>> RegsFromAssembly = new Queue<Action<IServiceCollection>>();
// 2. register entities (can overwrite)
private readonly Queue<Action<IServiceCollection>> RegsEntity = new Queue<Action<IServiceCollection>>();
// 3. register db set factories (can overwrite)
private readonly Queue<Action<IServiceCollection>> RegsDbSetFactory = new Queue<Action<IServiceCollection>>();
// 4. register repository
private readonly Queue<Action<IServiceCollection>> RegsRepository = new Queue<Action<IServiceCollection>>();
internal void RegisterAllServices(IServiceCollection services)
{ {
// 1. register from assembly // register services from configuration
RegsFromAssembly.InvokeAll(services); var cfg = new RepositoryConfiguration();
options.Invoke(cfg);
cfg.RegisterAllServices(services);
// 2. register entities (can overwrite) return services;
RegsEntity.InvokeAll(services);
// 3. register db set factories (can overwrite)
RegsDbSetFactory.InvokeAll(services);
} }
internal RepositoryConfiguration() { } public class RepositoryConfiguration
public void RegisterFromAssembly<TDbContext>(Assembly assembly) where TDbContext : DbContext
{ {
void reg(IServiceCollection services) // 1. register from assembly
private readonly Queue<Action<IServiceCollection>> RegsFromAssembly = new Queue<Action<IServiceCollection>>();
// 2. register entities (can overwrite)
private readonly Queue<Action<IServiceCollection>> RegsEntity = new Queue<Action<IServiceCollection>>();
// 3. register db set factories (can overwrite)
private readonly Queue<Action<IServiceCollection>> RegsDbSetFactory = new Queue<Action<IServiceCollection>>();
// 4. register repository
private readonly Queue<Action<IServiceCollection>> RegsRepository = new Queue<Action<IServiceCollection>>();
internal void RegisterAllServices(IServiceCollection services)
{ {
// scan all types in the Assembly // 1. register from assembly
var entityTypes = assembly.GetTypes() RegsFromAssembly.InvokeAll(services);
.Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute<TableAttribute>() != null);
foreach (var entityType in entityTypes) // 2. register entities (can overwrite)
RegsEntity.InvokeAll(services);
// 3. register db set factories (can overwrite)
RegsDbSetFactory.InvokeAll(services);
}
internal RepositoryConfiguration() { }
public void RegisterFromAssembly<TDbContext>(Assembly assembly) where TDbContext : DbContext
{
void reg(IServiceCollection services)
{ {
#region Repository // scan all types in the Assembly
/// register repository var entityTypes = assembly.GetTypes()
// create generic DbRepository<DbContext, TEntity> type .Where(t => t.IsClass && !t.IsAbstract && t.GetCustomAttribute<TableAttribute>() != null);
var repositoryType = typeof(DbRepository<,>).MakeGenericType(typeof(TDbContext), entityType);
var interfaceType = typeof(IRepository<>).MakeGenericType(entityType);
// add into DI container as Scoped foreach (var entityType in entityTypes)
services.AddScoped(interfaceType, repositoryType); {
#endregion Repository #region Repository
/// register repository
// create generic DbRepository<DbContext, TEntity> type
var repositoryType = typeof(DbRepository<,>).MakeGenericType(typeof(TDbContext), entityType);
var interfaceType = typeof(IRepository<>).MakeGenericType(entityType);
#region DbSetFactory // add into DI container as Scoped
/// register DbSetFactory services.AddScoped(interfaceType, repositoryType);
var addDbSetFactoryMethod = typeof(DependencyInjection) #endregion Repository
.GetMethod(nameof(AddDbSetFactory),
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var genericMethod = addDbSetFactoryMethod #region DbSetFactory
/// register DbSetFactory
var addDbSetFactoryMethod = typeof(DependencyInjection)
.GetMethod(nameof(AddDbSetFactory),
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
var genericMethod = addDbSetFactoryMethod
#if NET #if NET
! !
#endif #endif
.MakeGenericMethod(typeof(TDbContext), entityType); .MakeGenericMethod(typeof(TDbContext), entityType);
genericMethod.Invoke(null, new [] { services, null }); genericMethod.Invoke(null, new [] { services, null });
#endregion DbSetFactory #endregion DbSetFactory
}
} }
RegsFromAssembly.Enqueue(reg);
} }
RegsFromAssembly.Enqueue(reg); public void RegisterEntity<TDbContext, TEntity>(Func<TDbContext, DbSet<TEntity>>
}
public void RegisterEntity<TDbContext, TEntity>(Func<TDbContext, DbSet<TEntity>>
#if NET #if NET
? ?
#endif #endif
dbSetFactory = null) dbSetFactory = null)
where TDbContext : DbContext where TDbContext : DbContext
where TEntity : class where TEntity : class
{ {
void reg(IServiceCollection services) void reg(IServiceCollection services)
=> services => services
.AddScoped<IRepository<TEntity>, DbRepository<TDbContext, TEntity>>() .AddScoped<IRepository<TEntity>, DbRepository<TDbContext, TEntity>>()
.AddDbSetFactory(dbSetFactory); .AddDbSetFactory(dbSetFactory);
RegsEntity.Enqueue(reg); RegsEntity.Enqueue(reg);
}
public void RegisterDbSetFactory<TDbContext, TEntity>(Func<TDbContext, DbSet<TEntity>> dbSetFactory)
where TDbContext : DbContext
where TEntity : class
=> RegsDbSetFactory.Enqueue(s => s.AddDbSetFactory(dbSetFactory));
public void RegisterDefaultRepository<TDbContext>()
where TDbContext : DbContext
=> RegsRepository.Enqueue(s => s.AddScoped<IRepository, DbRepository<TDbContext>>());
} }
public void RegisterDbSetFactory<TDbContext, TEntity>(Func<TDbContext, DbSet<TEntity>> dbSetFactory) private static void InvokeAll<T>(this Queue<Action<T>> queue, T services)
where TDbContext : DbContext {
where TEntity : class while (queue.Count > 0)
=> RegsDbSetFactory.Enqueue(s => s.AddDbSetFactory(dbSetFactory)); queue.Dequeue().Invoke(services);
}
public void RegisterDefaultRepository<TDbContext>()
where TDbContext : DbContext
=> RegsRepository.Enqueue(s => s.AddScoped<IRepository, DbRepository<TDbContext>>());
}
private static void InvokeAll<T>(this Queue<Action<T>> queue, T services)
{
while (queue.Count > 0)
queue.Dequeue().Invoke(services);
}
internal static IServiceCollection AddDbSetFactory<TDbContext, TEntity>(this IServiceCollection services, Func<TDbContext, DbSet<TEntity>> internal static IServiceCollection AddDbSetFactory<TDbContext, TEntity>(this IServiceCollection services, Func<TDbContext, DbSet<TEntity>>
#if NET #if NET
? ?
#endif #endif
create = null) create = null)
where TDbContext : DbContext where TDbContext : DbContext
where TEntity : class where TEntity : class
{ {
#if NET #if NET
create ??= ctx => ctx.Set<TEntity>(); create ??= ctx => ctx.Set<TEntity>();
#elif NETFRAMEWORK #elif NETFRAMEWORK
if(create is null) if(create is null)
create = ctx => ctx.Set<TEntity>(); create = ctx => ctx.Set<TEntity>();
#endif #endif
services.AddSingleton(_ => new DbSetFactory<TDbContext, TEntity>(create)); services.AddSingleton(_ => new DbSetFactory<TDbContext, TEntity>(create));
return services; return services;
}
} }
} }
#if NETFRAMEWORK
}
#endif