* Removed `dbContextOptions` parameter from `AddEnvelopeGeneratorInfrastructureServices` * Moved `AddDbContext` registration into `Config` class with overloads for both `Action<DbContextOptionsBuilder>` and `Action<IServiceProvider, DbContextOptionsBuilder>` * Simplified service registration flow and improved extensibility
203 lines
8.9 KiB
C#
203 lines
8.9 KiB
C#
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using DigitalData.Core.Infrastructure;
|
|
using EnvelopeGenerator.Domain.Entities;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Dapper;
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
using System.Reflection;
|
|
using DigitalData.UserManager.Domain.Entities;
|
|
#if NET
|
|
using CommandDotNet.Execution;
|
|
using EnvelopeGenerator.Infrastructure.Repositories;
|
|
using EnvelopeGenerator.Infrastructure.Executor;
|
|
using EnvelopeGenerator.Application.Common.Interfaces.Repositories;
|
|
using EnvelopeGenerator.Application.Common.Interfaces.SQLExecutor;
|
|
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
|
|
#elif NETFRAMEWORK
|
|
using System;
|
|
#endif
|
|
|
|
namespace EnvelopeGenerator.Infrastructure
|
|
{
|
|
public static class DIExtensions
|
|
{
|
|
/// <summary>
|
|
/// Registers the required repositories for the Envelope Generator service to the given <see cref="IServiceCollection"/>.
|
|
/// This method adds the repositories for various envelope-related entities, such as configuration, document receivers, envelopes, and users,
|
|
/// as scoped services to the dependency injection container. Optionally, it can also configure the <see cref="EGDbContext"/>
|
|
/// with the provided database context options if specified.
|
|
/// </summary>
|
|
/// <param name="services">The <see cref="IServiceCollection"/> to which the services are added.</param>
|
|
/// <param name="dbContextOptions">An optional action to configure the <see cref="DbContextOptionsBuilder"/> for the <see cref="EGDbContext"/>.
|
|
/// If not provided, the <see cref="EGDbContext"/> will not be configured.</param>
|
|
/// <returns>The updated <see cref="IServiceCollection"/> with the added repository services.</returns>
|
|
/// <remarks>
|
|
/// This method ensures that the repositories are registered as scoped services, meaning that a new instance of each repository
|
|
/// will be created per HTTP request (or per scope) within the dependency injection container.
|
|
/// </remarks>
|
|
[Obsolete("Use IRepository")]
|
|
public static IServiceCollection AddEnvelopeGeneratorInfrastructureServices(this IServiceCollection services,
|
|
Action<Config> options
|
|
#if NET
|
|
, IConfiguration? sqlExecutorConfiguration = null,
|
|
Action<SQLExecutorParams>? sqlExecutorConfigureOptions = null
|
|
#endif
|
|
)
|
|
{
|
|
// configure custom options
|
|
options(new Config(services));
|
|
#if NET
|
|
services.TryAddScoped<IConfigRepository, ConfigRepository>();
|
|
services.TryAddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
|
services.TryAddScoped<IEnvelopeDocumentRepository, EnvelopeDocumentRepository>();
|
|
services.TryAddScoped<IDocumentReceiverElementRepository, DocumentReceiverElementRepository>();
|
|
services.TryAddScoped<IDocumentStatusRepository, DocumentStatusRepository>();
|
|
services.TryAddScoped<IEmailTemplateRepository, EmailTemplateRepository>();
|
|
services.TryAddScoped<IEnvelopeRepository, EnvelopeRepository>();
|
|
services.TryAddScoped<IEnvelopeHistoryRepository, EnvelopeHistoryRepository>();
|
|
services.TryAddScoped<IEnvelopeReceiverRepository, EnvelopeReceiverRepository>();
|
|
services.TryAddScoped<IEnvelopeTypeRepository, EnvelopeTypeRepository>();
|
|
services.TryAddScoped<IReceiverRepository, ReceiverRepository>();
|
|
services.TryAddScoped<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyRepository>();
|
|
#endif
|
|
|
|
services.AddDbRepository(opt =>
|
|
{
|
|
// scan EnvelopeGenerator
|
|
opt.RegisterFromAssembly<EGDbContext>(typeof(Config).Assembly);
|
|
|
|
// scan UserManager
|
|
opt.RegisterFromAssembly<EGDbContext>(typeof(User).Assembly);
|
|
|
|
#if NET
|
|
// scan EmailProfilerDispatcher
|
|
opt.RegisterFromAssembly<EGDbContext>(typeof(EmailOut).Assembly);
|
|
#endif
|
|
});
|
|
|
|
#if NET
|
|
services.AddSQLExecutor<Envelope>();
|
|
services.AddSQLExecutor<Receiver>();
|
|
services.AddSQLExecutor<Document>();
|
|
services.AddSQLExecutor<Signature>();
|
|
services.AddSQLExecutor<DocumentStatus>();
|
|
|
|
SetDapperTypeMap<Envelope>();
|
|
SetDapperTypeMap<User>();
|
|
SetDapperTypeMap<Receiver>();
|
|
SetDapperTypeMap<Document>();
|
|
SetDapperTypeMap<Signature>();
|
|
SetDapperTypeMap<DocumentStatus>();
|
|
|
|
services.AddScoped<IEnvelopeExecutor, EnvelopeExecutor>();
|
|
services.AddScoped<IEnvelopeReceiverExecutor, EnvelopeReceiverExecutor>();
|
|
services.AddScoped<IDocumentExecutor, DocumentExecutor>();
|
|
|
|
if (sqlExecutorConfiguration is not null || sqlExecutorConfigureOptions is not null)
|
|
services.AddSQLExecutor(sqlExecutorConfiguration, sqlExecutorConfigureOptions);
|
|
#endif
|
|
|
|
return services;
|
|
}
|
|
|
|
#if NET
|
|
public static IServiceCollection AddSQLExecutor(this IServiceCollection services, IConfiguration? configuration = null, Action<SQLExecutorParams>? configureOptions = null)
|
|
{
|
|
if (configuration is not null && configureOptions is not null)
|
|
throw new InvalidOperationException("Cannot use both 'configuration' and 'configureOptions'. Only one should be provided.");
|
|
|
|
if (configuration is not null)
|
|
services.Configure<SQLExecutorParams>(configuration);
|
|
|
|
if (configureOptions is not null)
|
|
services.Configure(configureOptions);
|
|
|
|
return services.AddSingleton<ISQLExecutor, SQLExecutor>();
|
|
}
|
|
|
|
private static void SetDapperTypeMap<TModel>()
|
|
{
|
|
Dapper.SqlMapper.SetTypeMap(typeof(TModel), new CustomPropertyTypeMap(
|
|
typeof(TModel),
|
|
(type, columnName) =>
|
|
{
|
|
return type.GetProperties().FirstOrDefault(prop =>
|
|
{
|
|
var attr = prop.GetCustomAttribute<ColumnAttribute>();
|
|
return attr != null && string.Equals(attr.Name, columnName, StringComparison.OrdinalIgnoreCase)
|
|
|| string.Equals(prop.Name, columnName, StringComparison.OrdinalIgnoreCase);
|
|
})!;
|
|
}
|
|
));
|
|
}
|
|
|
|
public static IServiceCollection AddSQLExecutor<T>(this IServiceCollection services, IConfiguration? configuration = null, Action<SQLExecutorParams>? configureOptions = null) where T : class
|
|
{
|
|
if (configuration is not null && configureOptions is not null)
|
|
throw new InvalidOperationException("Cannot use both 'configuration' and 'configureOptions'. Only one should be provided.");
|
|
|
|
if (configuration is not null)
|
|
services.Configure<SQLExecutorParams>(configuration);
|
|
|
|
services.AddScoped<ISQLExecutor<T>, SQLExecutor<T>>();
|
|
|
|
var interfaceType = typeof(ISQL<>);
|
|
var targetGenericType = interfaceType.MakeGenericType(typeof(T));
|
|
|
|
var implementations = AppDomain.CurrentDomain.GetAssemblies()
|
|
.SelectMany(a =>
|
|
{
|
|
try { return a.GetTypes(); }
|
|
catch { return Array.Empty<Type>(); }
|
|
})
|
|
.Where(t =>
|
|
t is { IsClass: true, IsAbstract: false } &&
|
|
t.GetInterfaces().Any(i =>
|
|
i.IsGenericType &&
|
|
i.GetGenericTypeDefinition() == interfaceType &&
|
|
i.GenericTypeArguments[0] == typeof(T)
|
|
)
|
|
);
|
|
|
|
foreach (var impl in implementations)
|
|
{
|
|
services.AddSingleton(impl);
|
|
}
|
|
|
|
return services;
|
|
}
|
|
#endif
|
|
|
|
public class Config
|
|
{
|
|
private readonly IServiceCollection _services;
|
|
|
|
internal Config(IServiceCollection services)
|
|
{
|
|
_services = services;
|
|
}
|
|
|
|
public void ConfigureDbTriggerParams(IConfiguration configuration)
|
|
{
|
|
_services.Configure<DbTriggerParams>(configuration.GetSection(nameof(DbTriggerParams)));
|
|
}
|
|
|
|
public void ConfigureDbTriggerParams(Action<DbTriggerParams> configureOptions)
|
|
{
|
|
_services.Configure(configureOptions);
|
|
}
|
|
|
|
public void AddDbContext(Action<DbContextOptionsBuilder> dbContextOptions)
|
|
{
|
|
_services.AddDbContext<EGDbContext>(dbContextOptions);
|
|
}
|
|
|
|
public void AddDbContext(Action<IServiceProvider, DbContextOptionsBuilder> dbContextOptions)
|
|
{
|
|
_services.AddDbContext<EGDbContext>(dbContextOptions);
|
|
}
|
|
}
|
|
}
|
|
} |