Updated code to support conditional compilation for .NET Framework and .NET. Introduced nullable reference types in `DbRepository.cs` and ensured proper initialization of service registration queues in `DependencyInjection.cs`. Modified `DbRepositoryFactory.cs` and `DbSetFactory.cs` to maintain consistent structure across frameworks. These changes enhance compatibility and improve type safety.
151 lines
5.2 KiB
C#
151 lines
5.2 KiB
C#
using DigitalData.Core.Abstraction.Application.Repository;
|
|
using DigitalData.Core.Infrastructure.Factory;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
using System.Reflection;
|
|
#if NETFRAMEWORK
|
|
using System.Collections.Generic;
|
|
using System;
|
|
using System.Linq;
|
|
#endif
|
|
|
|
namespace DigitalData.Core.Infrastructure
|
|
#if NET
|
|
;
|
|
#elif NETFRAMEWORK
|
|
{
|
|
#endif
|
|
|
|
public static class DependencyInjection
|
|
{
|
|
public static IServiceCollection AddDbRepository(this IServiceCollection services, Action<RepositoryConfiguration> options)
|
|
{
|
|
// register services from configuration
|
|
var cfg = new RepositoryConfiguration();
|
|
options.Invoke(cfg);
|
|
cfg.RegisterAllServices(services);
|
|
|
|
// register db repository
|
|
services.AddSingleton<IRepository, DbRepository>();
|
|
|
|
// register db repository factory
|
|
services.AddSingleton<IRepositoryFactory, DbRepositoryFactory>();
|
|
|
|
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>>();
|
|
|
|
internal void RegisterAllServices(IServiceCollection services)
|
|
{
|
|
// 1. register from assembly
|
|
RegsFromAssembly.InvokeAll(services);
|
|
|
|
// 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)
|
|
{
|
|
// 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)
|
|
{
|
|
#region Repository
|
|
/// register repository
|
|
// 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);
|
|
#endregion Repository
|
|
|
|
#region DbSetFactory
|
|
/// register DbSetFactory
|
|
var addDbSetFactoryMethod = typeof(DependencyInjection)
|
|
.GetMethod(nameof(AddDbSetFactory),
|
|
BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public);
|
|
|
|
var genericMethod = addDbSetFactoryMethod
|
|
#if NET
|
|
!
|
|
#endif
|
|
.MakeGenericMethod(typeof(TDbContext), entityType);
|
|
genericMethod.Invoke(null, new [] { services, null });
|
|
#endregion DbSetFactory
|
|
}
|
|
}
|
|
|
|
RegsFromAssembly.Enqueue(reg);
|
|
}
|
|
|
|
public void RegisterEntity<TDbContext, TEntity>(Func<TDbContext, DbSet<TEntity>>
|
|
#if NET
|
|
?
|
|
#endif
|
|
dbSetFactory = null)
|
|
where TDbContext : DbContext
|
|
where TEntity : class
|
|
{
|
|
void reg(IServiceCollection services)
|
|
=> services
|
|
.AddScoped<IRepository<TEntity>, DbRepository<TDbContext, TEntity>>()
|
|
.AddDbSetFactory(dbSetFactory);
|
|
|
|
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));
|
|
}
|
|
|
|
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>>
|
|
#if NET
|
|
?
|
|
#endif
|
|
create = null)
|
|
where TDbContext : DbContext
|
|
where TEntity : class
|
|
{
|
|
#if NET
|
|
create ??= ctx => ctx.Set<TEntity>();
|
|
#elif NETFRAMEWORK
|
|
if(create is null)
|
|
create = ctx => ctx.Set<TEntity>();
|
|
#endif
|
|
services.AddSingleton(_ => new DbSetFactory<TDbContext, TEntity>(create));
|
|
return services;
|
|
}
|
|
}
|
|
|
|
#if NETFRAMEWORK
|
|
}
|
|
#endif |