This commit removes the IEnvelopeExecutor interface and its implementation, replacing it with ISQLExecutor. The CreateEnvelopeAsync method in Extension.cs now directly creates DynamicParameters. The CreateEnvelopeCommandHandler has been updated to utilize ISQLExecutor. Additionally, the EnvelopeExecutor class has been removed, and a new SQL command class, EnvelopeReceiverCreateReadSQL, has been added for managing envelope receiver SQL operations.
157 lines
8.4 KiB
C#
157 lines
8.4 KiB
C#
using EnvelopeGenerator.Application.Contracts.Repositories;
|
|
using EnvelopeGenerator.Infrastructure.Repositories;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using DigitalData.Core.Infrastructure;
|
|
using EnvelopeGenerator.Domain.Entities;
|
|
using DigitalData.Core.Infrastructure.AutoMapper;
|
|
using EnvelopeGenerator.Application.Contracts.SQLExecutor;
|
|
using Microsoft.Extensions.Configuration;
|
|
using EnvelopeGenerator.Infrastructure.Executor;
|
|
using Dapper;
|
|
using System.ComponentModel.DataAnnotations.Schema;
|
|
using System.Reflection;
|
|
using DigitalData.UserManager.Domain.Entities;
|
|
|
|
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>
|
|
public static IServiceCollection AddEnvelopeGeneratorInfrastructureServices(this IServiceCollection services,
|
|
Action<DbContextOptionsBuilder>? dbContextOptions = null,
|
|
IConfiguration? sqlExecutorConfiguration = null,
|
|
Action<SQLExecutorParams>? sqlExecutorConfigureOptions = null)
|
|
{
|
|
if(dbContextOptions is not null)
|
|
services.AddDbContext<EGDbContext>(dbContextOptions);
|
|
|
|
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<IEnvelopeCertificateRepository, EnvelopeCertificateRepository>();
|
|
services.TryAddScoped<IEnvelopeHistoryRepository, EnvelopeHistoryRepository>();
|
|
services.TryAddScoped<IEnvelopeReceiverRepository, EnvelopeReceiverRepository>();
|
|
services.TryAddScoped<IEnvelopeTypeRepository, EnvelopeTypeRepository>();
|
|
services.TryAddScoped<IReceiverRepository, ReceiverRepository>();
|
|
services.TryAddScoped<IUserReceiverRepository, UserReceiverRepository>();
|
|
services.TryAddScoped<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyRepository>();
|
|
|
|
services.AddDbRepository<EGDbContext, Config>(context => context.Configs).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, DocumentReceiverElement>(context => context.DocumentReceiverElements).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, EnvelopeDocument>(context => context.EnvelopeDocument).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, DocumentStatus>(context => context.DocumentStatus).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, EmailTemplate>(context => context.EmailTemplate).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, Envelope>(context => context.Envelopes).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, EnvelopeCertificate>(context => context.EnvelopeCertificates).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, EnvelopeHistory>(context => context.EnvelopeHistories).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, EnvelopeReceiver>(context => context.EnvelopeReceivers).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, EnvelopeType>(context => context.EnvelopeTypes).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, Receiver>(context => context.Receivers).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, UserReceiver>(context => context.UserReceivers).UseAutoMapper();
|
|
services.AddDbRepository<EGDbContext, EnvelopeReceiverReadOnly>(context => context.EnvelopeReceiverReadOnlys).UseAutoMapper();
|
|
|
|
services.AddSQLExecutor<Envelope>();
|
|
services.AddSQLExecutor<Receiver>();
|
|
services.AddSQLExecutor<EnvelopeDocument>();
|
|
services.AddSQLExecutor<DocumentReceiverElement>();
|
|
services.AddSQLExecutor<DocumentStatus>();
|
|
|
|
SetDapperTypeMap<Envelope>();
|
|
SetDapperTypeMap<User>();
|
|
SetDapperTypeMap<Receiver>();
|
|
SetDapperTypeMap<EnvelopeDocument>();
|
|
SetDapperTypeMap<DocumentReceiverElement>();
|
|
SetDapperTypeMap<DocumentStatus>();
|
|
|
|
if (sqlExecutorConfiguration is not null || sqlExecutorConfigureOptions is not null)
|
|
services.AddSQLExecutor(sqlExecutorConfiguration, sqlExecutorConfigureOptions);
|
|
|
|
return services;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|