From 9c867ac8aa0b11dc6476eaf756f7c61aedb3053e Mon Sep 17 00:00:00 2001 From: TekH Date: Wed, 1 Oct 2025 10:51:50 +0200 Subject: [PATCH] =?UTF-8?q?refactor(DIExtensions):=20Hinzuf=C3=BCgen=20ein?= =?UTF-8?q?er=20bedingten=20NET/NETFRAMEWORK-Unterst=C3=BCtzung=20in=20DIE?= =?UTF-8?q?xtensions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Umschlossene Repository- und Executor-Registrierungen mit `#if NET`, um die Kompatibilität zwischen .NET und .NET Framework sicherzustellen - Hinzufügen des Abschnitts `#elif NETFRAMEWORK` für frameworkspezifische Importe - Verschieben der SQLExecutor- und Dapper-Typzuordnung unter bedingte Kompilierung - Anpassen der Methodensignaturen zur Unterstützung bedingter nullbarer Parameter --- .../DependencyExtensions.cs | 270 ++++++++++-------- 1 file changed, 145 insertions(+), 125 deletions(-) diff --git a/EnvelopeGenerator.Infrastructure/DependencyExtensions.cs b/EnvelopeGenerator.Infrastructure/DependencyExtensions.cs index 484bee9b..88fba5ab 100644 --- a/EnvelopeGenerator.Infrastructure/DependencyExtensions.cs +++ b/EnvelopeGenerator.Infrastructure/DependencyExtensions.cs @@ -1,157 +1,177 @@ -using EnvelopeGenerator.Infrastructure.Repositories; -using Microsoft.Extensions.DependencyInjection; +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 EnvelopeGenerator.Infrastructure.Executor; using Dapper; using System.ComponentModel.DataAnnotations.Schema; using System.Reflection; using DigitalData.UserManager.Domain.Entities; +#if NET +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 +namespace EnvelopeGenerator.Infrastructure { - /// - /// Registers the required repositories for the Envelope Generator service to the given . - /// 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 - /// with the provided database context options if specified. - /// - /// The to which the services are added. - /// An optional action to configure the for the . - /// If not provided, the will not be configured. - /// The updated with the added repository services. - /// - /// 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. - /// - [Obsolete("Use IRepository")] - public static IServiceCollection AddEnvelopeGeneratorInfrastructureServices(this IServiceCollection services, - Action? dbContextOptions = null, - IConfiguration? sqlExecutorConfiguration = null, - Action? sqlExecutorConfigureOptions = null) + public static class DIExtensions { - if(dbContextOptions is not null) - services.AddDbContext(dbContextOptions); - - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - services.TryAddScoped(); - - services.AddDbRepository(opt => + /// + /// Registers the required repositories for the Envelope Generator service to the given . + /// 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 + /// with the provided database context options if specified. + /// + /// The to which the services are added. + /// An optional action to configure the for the . + /// If not provided, the will not be configured. + /// The updated with the added repository services. + /// + /// 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. + /// + [Obsolete("Use IRepository")] + public static IServiceCollection AddEnvelopeGeneratorInfrastructureServices(this IServiceCollection services, + Action +#if NET + ? +#endif + dbContextOptions = null +#if NET + , IConfiguration? sqlExecutorConfiguration = null, + Action? sqlExecutorConfigureOptions = null +#endif + ) { - // scan EnvelopeGenerator - opt.RegisterFromAssembly(typeof(Config).Assembly); - - // scan UserManager - opt.RegisterFromAssembly(typeof(User).Assembly); - - // scan EmailProfilerDispatcher - opt.RegisterFromAssembly(typeof(EmailOut).Assembly); - }); + if (dbContextOptions != null) + services.AddDbContext(dbContextOptions); + +#if NET + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); + services.TryAddScoped(); +#endif + + services.AddDbRepository(opt => + { + // scan EnvelopeGenerator + opt.RegisterFromAssembly(typeof(Config).Assembly); + + // scan UserManager + opt.RegisterFromAssembly(typeof(User).Assembly); + +#if NET + // scan EmailProfilerDispatcher + opt.RegisterFromAssembly(typeof(EmailOut).Assembly); +#endif + }); + +#if NET + services.AddSQLExecutor(); + services.AddSQLExecutor(); + services.AddSQLExecutor(); + services.AddSQLExecutor(); + services.AddSQLExecutor(); + + SetDapperTypeMap(); + SetDapperTypeMap(); + SetDapperTypeMap(); + SetDapperTypeMap(); + SetDapperTypeMap(); + SetDapperTypeMap(); + + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + if (sqlExecutorConfiguration is not null || sqlExecutorConfigureOptions is not null) + services.AddSQLExecutor(sqlExecutorConfiguration, sqlExecutorConfigureOptions); +#endif + + return services; + } - services.AddSQLExecutor(); - services.AddSQLExecutor(); - services.AddSQLExecutor(); - services.AddSQLExecutor(); - services.AddSQLExecutor(); +#if NET + public static IServiceCollection AddSQLExecutor(this IServiceCollection services, IConfiguration? configuration = null, Action? 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."); - SetDapperTypeMap(); - SetDapperTypeMap(); - SetDapperTypeMap(); - SetDapperTypeMap(); - SetDapperTypeMap(); - SetDapperTypeMap(); + if (configuration is not null) + services.Configure(configuration); - services.AddScoped(); - services.AddScoped(); - services.AddScoped(); + if (configureOptions is not null) + services.Configure(configureOptions); - if (sqlExecutorConfiguration is not null || sqlExecutorConfigureOptions is not null) - services.AddSQLExecutor(sqlExecutorConfiguration, sqlExecutorConfigureOptions); + return services.AddSingleton(); + } - return services; - } + private static void SetDapperTypeMap() + { + Dapper.SqlMapper.SetTypeMap(typeof(TModel), new CustomPropertyTypeMap( + typeof(TModel), + (type, columnName) => + { + return type.GetProperties().FirstOrDefault(prop => + { + var attr = prop.GetCustomAttribute(); + return attr != null && string.Equals(attr.Name, columnName, StringComparison.OrdinalIgnoreCase) + || string.Equals(prop.Name, columnName, StringComparison.OrdinalIgnoreCase); + })!; + } + )); + } - public static IServiceCollection AddSQLExecutor(this IServiceCollection services, IConfiguration? configuration = null, Action? 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."); + public static IServiceCollection AddSQLExecutor(this IServiceCollection services, IConfiguration? configuration = null, Action? 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(configuration); + if (configuration is not null) + services.Configure(configuration); - if(configureOptions is not null) - services.Configure(configureOptions); + services.AddScoped, SQLExecutor>(); - return services.AddSingleton(); - } + var interfaceType = typeof(ISQL<>); + var targetGenericType = interfaceType.MakeGenericType(typeof(T)); - private static void SetDapperTypeMap() - { - Dapper.SqlMapper.SetTypeMap(typeof(TModel), new CustomPropertyTypeMap( - typeof(TModel), - (type, columnName) => - { - return type.GetProperties().FirstOrDefault(prop => + var implementations = AppDomain.CurrentDomain.GetAssemblies() + .SelectMany(a => { - var attr = prop.GetCustomAttribute(); - return attr != null && string.Equals(attr.Name, columnName, StringComparison.OrdinalIgnoreCase) - || string.Equals(prop.Name, columnName, StringComparison.OrdinalIgnoreCase); - })!; + try { return a.GetTypes(); } + catch { return Array.Empty(); } + }) + .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); } - )); - } - - public static IServiceCollection AddSQLExecutor(this IServiceCollection services, IConfiguration? configuration = null, Action? 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(configuration); - - services.AddScoped, SQLExecutor>(); - - 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(); } - }) - .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; } - - return services; +#endif } } \ No newline at end of file