feat: tweaks
This commit is contained in:
@@ -12,7 +12,8 @@ public static class ServicesCollectionExtensions
|
||||
public static void AddApplication(this IServiceCollection services)
|
||||
{
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
services.AddMediatR(executingAssembly);
|
||||
services.AddValidatorsFromAssemblies(new[] { executingAssembly });
|
||||
services
|
||||
.AddMediatR(executingAssembly)
|
||||
.AddValidatorsFromAssemblies(new[] { executingAssembly });
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Shop.Core.AppSettings;
|
||||
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
|
||||
public sealed class CacheOptions : IAppOptions
|
||||
{
|
||||
public const string ConfigSectionPath = nameof(CacheOptions);
|
||||
static string IAppOptions.ConfigSectionPath => nameof(CacheOptions);
|
||||
|
||||
public int AbsoluteExpirationInHours { get; private init; }
|
||||
public int SlidingExpirationInSeconds { get; private init; }
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Shop.Core.AppSettings;
|
||||
[SuppressMessage("ReSharper", "UnusedAutoPropertyAccessor.Local")]
|
||||
public sealed class ConnectionOptions : IAppOptions
|
||||
{
|
||||
public const string ConfigSectionPath = "ConnectionStrings";
|
||||
static string IAppOptions.ConfigSectionPath => "ConnectionStrings";
|
||||
|
||||
[Required]
|
||||
public string SqlConnection { get; private init; }
|
||||
|
||||
@@ -6,17 +6,17 @@ namespace Shop.Core.Extensions;
|
||||
|
||||
public static class ConfigurationExtensions
|
||||
{
|
||||
private static readonly Action<BinderOptions> ConfigureBinderOptions
|
||||
= options => options.BindNonPublicProperties = true;
|
||||
private static readonly Action<BinderOptions> ConfigureBinderOptions = options =>
|
||||
options.BindNonPublicProperties = true;
|
||||
|
||||
/// <summary>
|
||||
/// Get options from IConfiguration object.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOptions">The type of options to retrieve.</typeparam>
|
||||
/// <param name="configuration">The IConfiguration object.</param>
|
||||
/// <param name="configSectionPath">The configuration section path.</param>
|
||||
/// <returns>The options object.</returns>
|
||||
public static TOptions GetOptions<TOptions>(this IConfiguration configuration, string configSectionPath)
|
||||
where TOptions : class, IAppOptions =>
|
||||
configuration.GetRequiredSection(configSectionPath).Get<TOptions>(ConfigureBinderOptions);
|
||||
public static TOptions GetOptions<TOptions>(this IConfiguration configuration) where TOptions : class, IAppOptions
|
||||
=> configuration
|
||||
.GetRequiredSection(TOptions.ConfigSectionPath)
|
||||
.Get<TOptions>(ConfigureBinderOptions);
|
||||
}
|
||||
@@ -11,38 +11,30 @@ namespace Shop.Core.Extensions;
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static class ServicesCollectionExtensions
|
||||
{
|
||||
private static readonly Action<BinderOptions> ConfigureBinderOptions
|
||||
= options => options.BindNonPublicProperties = true;
|
||||
private static readonly Action<BinderOptions> ConfigureBinderOptions = options =>
|
||||
options.BindNonPublicProperties = true;
|
||||
|
||||
public static void AddCorrelationGenerator(this IServiceCollection services) =>
|
||||
services.AddScoped<ICorrelationIdGenerator, CorrelationIdGenerator>();
|
||||
|
||||
public static void ConfigureAppSettings(this IServiceCollection services)
|
||||
{
|
||||
services.AddOptionsWithValidation<ConnectionOptions>(ConnectionOptions.ConfigSectionPath);
|
||||
services.AddOptionsWithValidation<CacheOptions>(CacheOptions.ConfigSectionPath);
|
||||
}
|
||||
public static void ConfigureAppSettings(this IServiceCollection services) =>
|
||||
services
|
||||
.AddOptionsWithValidation<ConnectionOptions>()
|
||||
.AddOptionsWithValidation<CacheOptions>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds options with validation to the service collection.
|
||||
/// </summary>
|
||||
/// <typeparam name="TOptions">The type of options to add.</typeparam>
|
||||
/// <param name="services">The service collection.</param>
|
||||
/// <param name="configSectionPath">The configuration section path.</param>
|
||||
private static void AddOptionsWithValidation<TOptions>(this IServiceCollection services, string configSectionPath)
|
||||
private static IServiceCollection AddOptionsWithValidation<TOptions>(this IServiceCollection services)
|
||||
where TOptions : class, IAppOptions
|
||||
{
|
||||
// Adds options of type TOptions to the service collection.
|
||||
services
|
||||
return services
|
||||
.AddOptions<TOptions>()
|
||||
|
||||
// Binds the configuration section specified by configSectionPath to the options.
|
||||
.BindConfiguration(configSectionPath, ConfigureBinderOptions)
|
||||
|
||||
// Validates the options using data annotations.
|
||||
.BindConfiguration(TOptions.ConfigSectionPath, ConfigureBinderOptions)
|
||||
.ValidateDataAnnotations()
|
||||
|
||||
// Performs additional validation on start.
|
||||
.ValidateOnStart();
|
||||
.ValidateOnStart()
|
||||
.Services;
|
||||
}
|
||||
}
|
||||
@@ -5,4 +5,8 @@ namespace Shop.Core.SharedKernel;
|
||||
/// </summary>
|
||||
public interface IAppOptions
|
||||
{
|
||||
/// <summary>
|
||||
/// The configuration section path.
|
||||
/// </summary>
|
||||
static abstract string ConfigSectionPath { get; }
|
||||
}
|
||||
@@ -14,24 +14,18 @@ namespace Shop.Infrastructure.Extensions;
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static class ServicesCollectionExtensions
|
||||
{
|
||||
public static void AddMemoryCacheService(this IServiceCollection services)
|
||||
=> services.AddScoped<ICacheService, MemoryCacheService>();
|
||||
public static void AddMemoryCacheService(this IServiceCollection services) =>
|
||||
services.AddScoped<ICacheService, MemoryCacheService>();
|
||||
|
||||
public static void AddDistributedCacheService(this IServiceCollection services)
|
||||
=> services.AddScoped<ICacheService, DistributedCacheService>();
|
||||
public static void AddDistributedCacheService(this IServiceCollection services) =>
|
||||
services.AddScoped<ICacheService, DistributedCacheService>();
|
||||
|
||||
public static void AddInfrastructure(this IServiceCollection services)
|
||||
{
|
||||
// MediatR Pipelines
|
||||
services.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
|
||||
|
||||
// Repositories
|
||||
services.AddScoped<IEventStoreRepository, EventStoreRepository>();
|
||||
services.AddScoped<ICustomerWriteOnlyRepository, CustomerWriteOnlyRepository>();
|
||||
|
||||
// Database Contexts
|
||||
services.AddScoped<WriteDbContext>();
|
||||
services.AddScoped<EventStoreDbContext>();
|
||||
services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||
}
|
||||
public static void AddInfrastructure(this IServiceCollection services) =>
|
||||
services
|
||||
.AddScoped(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>))
|
||||
.AddScoped<IEventStoreRepository, EventStoreRepository>()
|
||||
.AddScoped<ICustomerWriteOnlyRepository, CustomerWriteOnlyRepository>()
|
||||
.AddScoped<WriteDbContext>()
|
||||
.AddScoped<EventStoreDbContext>()
|
||||
.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||
}
|
||||
@@ -56,7 +56,7 @@ internal static class ServicesCollectionExtensions
|
||||
|
||||
public static void AddHealthChecks(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var connectionOptions = configuration.GetOptions<ConnectionOptions>(ConnectionOptions.ConfigSectionPath);
|
||||
var connectionOptions = configuration.GetOptions<ConnectionOptions>();
|
||||
|
||||
var healthCheckBuilder = services
|
||||
.AddHealthChecks()
|
||||
@@ -79,14 +79,12 @@ internal static class ServicesCollectionExtensions
|
||||
|
||||
public static void AddCacheService(this IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
var connectionOptions = configuration.GetOptions<ConnectionOptions>(ConnectionOptions.ConfigSectionPath);
|
||||
var connectionOptions = configuration.GetOptions<ConnectionOptions>();
|
||||
if (connectionOptions.CacheConnection.IsInMemoryCache())
|
||||
{
|
||||
// ASP.NET Core Memory Cache.
|
||||
services.AddMemoryCache();
|
||||
|
||||
// Shop Infra Service.
|
||||
services.AddMemoryCacheService();
|
||||
services
|
||||
.AddMemoryCache() // ASP.NET Core Memory Cache.
|
||||
.AddMemoryCacheService();// Shop Infra Service.
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -96,10 +94,7 @@ internal static class ServicesCollectionExtensions
|
||||
{
|
||||
options.InstanceName = "master";
|
||||
options.Configuration = connectionOptions.CacheConnection;
|
||||
});
|
||||
|
||||
// Shop Infra Service.
|
||||
services.AddDistributedCacheService();
|
||||
}).AddDistributedCacheService(); // Shop Infra Service.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,13 +111,10 @@ internal static class ServicesCollectionExtensions
|
||||
var connectionOptions = serviceProvider.GetOptions<ConnectionOptions>();
|
||||
|
||||
optionsBuilder.UseSqlServer(connectionOptions.SqlConnection, sqlServerOptions =>
|
||||
{
|
||||
sqlServerOptions.MigrationsAssembly(MigrationsAssembly);
|
||||
|
||||
// Configure connection resiliency with retry on failure and a command timeout of 60 seconds.
|
||||
sqlServerOptions.EnableRetryOnFailure(3);
|
||||
sqlServerOptions.CommandTimeout(60);
|
||||
}).UseQueryTrackingBehavior(queryTrackingBehavior);
|
||||
sqlServerOptions
|
||||
.MigrationsAssembly(MigrationsAssembly)
|
||||
.EnableRetryOnFailure(3) // Configure connection resiliency with retry on failure.
|
||||
.CommandTimeout(60)).UseQueryTrackingBehavior(queryTrackingBehavior);
|
||||
|
||||
// Log retry attempts for execution strategy.
|
||||
optionsBuilder.LogTo(
|
||||
@@ -145,6 +137,10 @@ internal static class ServicesCollectionExtensions
|
||||
// Enable detailed errors and sensitive data logging if the environment is "development".
|
||||
var environment = serviceProvider.GetRequiredService<IHostEnvironment>();
|
||||
if (environment.IsDevelopment())
|
||||
optionsBuilder.EnableDetailedErrors().EnableSensitiveDataLogging();
|
||||
{
|
||||
optionsBuilder
|
||||
.EnableDetailedErrors()
|
||||
.EnableSensitiveDataLogging();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,13 +20,11 @@ public static class ServicesCollectionExtensions
|
||||
public static void AddQuery(this IServiceCollection services)
|
||||
{
|
||||
var executingAssembly = Assembly.GetExecutingAssembly();
|
||||
services.AddMediatR(executingAssembly);
|
||||
|
||||
// Add AutoMapper as a singleton instance
|
||||
services.AddSingleton<IMapper>(new Mapper(new MapperConfiguration(cfg => cfg.AddMaps(executingAssembly))));
|
||||
services.AddValidatorsFromAssembly(executingAssembly);
|
||||
services.AddSingleton<IReadDbContext, ReadDbContext>();
|
||||
services.AddScoped<ICustomerReadOnlyRepository, CustomerReadOnlyRepository>();
|
||||
services
|
||||
.AddMediatR(executingAssembly)
|
||||
.AddSingleton<IMapper>(new Mapper(new MapperConfiguration(cfg => cfg.AddMaps(executingAssembly))))
|
||||
.AddValidatorsFromAssembly(executingAssembly).AddSingleton<IReadDbContext, ReadDbContext>()
|
||||
.AddScoped<ICustomerReadOnlyRepository, CustomerReadOnlyRepository>();
|
||||
|
||||
ConfigureMongoDb();
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ConfigurationExtensionsTests
|
||||
var configuration = configurationBuilder.Build();
|
||||
|
||||
// Act
|
||||
var act = configuration.GetOptions<CacheOptions>(CacheOptions.ConfigSectionPath);
|
||||
var act = configuration.GetOptions<CacheOptions>();
|
||||
|
||||
// Assert
|
||||
act.Should().NotBeNull();
|
||||
|
||||
Reference in New Issue
Block a user