Developer 02 05568b1551 Add conditional compilation for .NET Framework support
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.
2025-09-30 18:36:15 +02:00

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