| | | 1 | | using Microsoft.Extensions.DependencyInjection.Extensions; |
| | | 2 | | |
| | | 3 | | namespace ZhEaIsNsAaBn.Infrastructure.Core; |
| | | 4 | | |
| | | 5 | | /// <summary>Records the registration mode of one context; <see cref="Register"/> runs when the root builder builds.</su |
| | | 6 | | /// <typeparam name="TDbContext">The context type.</typeparam> |
| | | 7 | | internal sealed class InfrastructureBuilder< TDbContext > : IInfrastructureBuilder<TDbContext> |
| | | 8 | | where TDbContext : DbContext |
| | | 9 | | { |
| | | 10 | | private readonly Action<DbContextOptionsBuilder> _dbContextOptionsBuilder; |
| | 152 | 11 | | private readonly List<Action<IServiceProvider, DbContextOptionsBuilder>> _extraOptions = []; |
| | | 12 | | private readonly InfrastructureBuilder _root; |
| | | 13 | | private Action<IServiceProvider, DbContextOptionsBuilder>? _auditing; |
| | 152 | 14 | | private ServiceLifetime _contextLifetime = ServiceLifetime.Scoped; |
| | | 15 | | private int? _poolSize; |
| | | 16 | | private bool _softDeleteFilter; |
| | | 17 | | |
| | | 18 | | |
| | 152 | 19 | | internal InfrastructureBuilder( InfrastructureBuilder root, Action<DbContextOptionsBuilder> dbContextOptionsBuilder |
| | | 20 | | { |
| | 152 | 21 | | _root = root; |
| | 152 | 22 | | _dbContextOptionsBuilder = dbContextOptionsBuilder; |
| | 152 | 23 | | } |
| | | 24 | | |
| | | 25 | | |
| | 0 | 26 | | public IServiceCollection Services => _root.Services; |
| | | 27 | | |
| | | 28 | | |
| | | 29 | | public IInfrastructureBuilder<TDbContext> AsCustom( ServiceLifetime contextLifetime ) |
| | | 30 | | { |
| | 32 | 31 | | _contextLifetime = contextLifetime; |
| | 32 | 32 | | _poolSize = null; |
| | | 33 | | |
| | 32 | 34 | | return this; |
| | | 35 | | } |
| | | 36 | | |
| | | 37 | | public IInfrastructureBuilder<TDbContext> AsFactoryPool( int poolSize = 1024 ) |
| | | 38 | | { |
| | 56 | 39 | | ArgumentOutOfRangeException.ThrowIfNegativeOrZero( poolSize ); |
| | | 40 | | |
| | 56 | 41 | | _poolSize = poolSize; |
| | | 42 | | |
| | 56 | 43 | | return this; |
| | | 44 | | } |
| | | 45 | | |
| | 24 | 46 | | public IInfrastructureBuilder<TDbContext> AsScoped() => AsCustom( ServiceLifetime.Scoped ); |
| | | 47 | | |
| | | 48 | | public IInfrastructureBuilder<TDbContext> ConfigureDbContextOptions( Action<DbContextOptionsBuilder> configure ) |
| | | 49 | | { |
| | 60 | 50 | | ArgumentNullException.ThrowIfNull( configure ); |
| | | 51 | | |
| | 56 | 52 | | _extraOptions.Add( ( _, options ) => configure( options ) ); |
| | | 53 | | |
| | 56 | 54 | | return this; |
| | | 55 | | } |
| | | 56 | | |
| | | 57 | | public IInfrastructureBuilder<TDbContext> ConfigureDbContextOptions( Action<IServiceProvider, DbContextOptionsBuilde |
| | | 58 | | { |
| | 16 | 59 | | ArgumentNullException.ThrowIfNull( configure ); |
| | | 60 | | |
| | 12 | 61 | | _extraOptions.Add( configure ); |
| | | 62 | | |
| | 12 | 63 | | return this; |
| | | 64 | | } |
| | | 65 | | |
| | | 66 | | public IInfrastructureBuilder<TDbContext> WithAuditing< TId >( Action<AuditOptions<TId>> configure ) |
| | | 67 | | where TId : struct, IEquatable<TId> |
| | | 68 | | { |
| | | 69 | | // Configured and checked now (fails fast); the interceptor is created with the options, in Build()'s registrati |
| | 20 | 70 | | var auditOptions = AuditingOptionsExtensions.AuditOptionsFrom( configure ); |
| | | 71 | | |
| | 16 | 72 | | _auditing = ( serviceProvider, options ) => options.AddInterceptors( new AuditInterceptor<TId>( auditOptions, se |
| | | 73 | | |
| | 16 | 74 | | return this; |
| | | 75 | | } |
| | | 76 | | |
| | | 77 | | public IInfrastructureBuilder<TDbContext> WithSoftDeleteFilter() |
| | | 78 | | { |
| | 8 | 79 | | _softDeleteFilter = true; |
| | | 80 | | |
| | 8 | 81 | | return this; |
| | | 82 | | } |
| | | 83 | | |
| | 112 | 84 | | public IServiceCollection Build() => _root.Build(); |
| | | 85 | | |
| | | 86 | | public IInfrastructureBuilder<TDbContext> WithRepository< TService, TImplementation >( ServiceLifetime lifetime = Se |
| | | 87 | | where TService : class |
| | | 88 | | where TImplementation : class, TService |
| | | 89 | | { |
| | 28 | 90 | | _root.Record( services => |
| | 28 | 91 | | { |
| | 28 | 92 | | services.RemoveAll<TService>(); |
| | 28 | 93 | | services.Add( new ServiceDescriptor( typeof( TService ), typeof( TImplementation ), lifetime ) ); |
| | 28 | 94 | | } ); |
| | | 95 | | |
| | 28 | 96 | | return this; |
| | | 97 | | } |
| | | 98 | | |
| | | 99 | | public IInfrastructureBuilder<TOtherDbContext> WithDbContext< TOtherDbContext >( Action<DbContextOptionsBuilder> dbC |
| | | 100 | | where TOtherDbContext : DbContext |
| | 20 | 101 | | => _root.WithDbContext<TOtherDbContext>( dbContextOptionsBuilder ); |
| | | 102 | | |
| | | 103 | | internal void Register( IServiceCollection services ) |
| | | 104 | | { |
| | | 105 | | // The context's own action first, then the recorded extras (e.g. a provider's options extension), auditing, the |
| | 132 | 106 | | var extras = _extraOptions.ToArray(); |
| | 132 | 107 | | var auditing = _auditing; |
| | 132 | 108 | | var softDeleteFilter = _softDeleteFilter; |
| | | 109 | | |
| | | 110 | | void ConfigureOptions( IServiceProvider serviceProvider, DbContextOptionsBuilder options ) |
| | | 111 | | { |
| | | 112 | | _dbContextOptionsBuilder( options ); |
| | | 113 | | |
| | | 114 | | foreach ( var extra in extras ) { extra( serviceProvider, options ); } |
| | | 115 | | |
| | | 116 | | auditing?.Invoke( serviceProvider, options ); |
| | | 117 | | |
| | | 118 | | if ( softDeleteFilter ) { options.UseSoftDeleteFilter(); } |
| | | 119 | | } |
| | | 120 | | |
| | | 121 | | |
| | 132 | 122 | | if ( _poolSize is { } poolSize ) |
| | | 123 | | { |
| | 48 | 124 | | services.AddPooledDbContextFactory<TDbContext>( ConfigureOptions, poolSize ); |
| | 48 | 125 | | services.TryAddScoped<IDbContextProvider<TDbContext>>( sp => new DbContextProvider<TDbContext>( sp.GetRequir |
| | | 126 | | |
| | | 127 | | |
| | 48 | 128 | | return; |
| | | 129 | | } |
| | | 130 | | |
| | | 131 | | |
| | 84 | 132 | | var optionsLifetime = _contextLifetime == ServiceLifetime.Singleton ? ServiceLifetime.Singleton : ServiceLifetim |
| | | 133 | | |
| | | 134 | | |
| | 84 | 135 | | services.AddDbContext<TDbContext>( ConfigureOptions, _contextLifetime, optionsLifetime ); |
| | 84 | 136 | | services.TryAdd( new ServiceDescriptor( typeof( IDbContextProvider<TDbContext> ), |
| | 84 | 137 | | sp => new DbContextProvider<TDbContext>( sp.GetRequiredService<TDbContex |
| | 84 | 138 | | _contextLifetime ) ); |
| | 84 | 139 | | } |
| | | 140 | | } |