diff --git a/Readme.md b/Readme.md index 1b3e2a3..072418b 100644 --- a/Readme.md +++ b/Readme.md @@ -69,3 +69,19 @@ public static T GetConfig(this IConfiguration configuration, string sectionNa ``` Gets config of type `T` from configuration, validates and returns it. Use this method when you don't need to add IOptions and you want to get validated config inside `ConfigureServices` method and use right away + +#### Configure +```csharp +public static IServiceCollection Configure(this IServiceCollection services, Action configure) + where T : class, new() +``` +Supports configuring your service through the provision of an `Action` parameter. + +Example usage: +```csharp +services.Configure(options => configuration.Bind(options)); +``` +Or: +```csharp +services.Configure(options => options.BaseAddress = new Uri("http://localhost:443")) +``` \ No newline at end of file diff --git a/src/Rtl.Configuration.Validation/ServiceCollectionExtensions.cs b/src/Rtl.Configuration.Validation/ServiceCollectionExtensions.cs index 23caeed..b768949 100644 --- a/src/Rtl.Configuration.Validation/ServiceCollectionExtensions.cs +++ b/src/Rtl.Configuration.Validation/ServiceCollectionExtensions.cs @@ -1,4 +1,5 @@ -using System.Linq; +using System; +using System.Linq; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -16,6 +17,12 @@ public static IServiceCollection AddConfig(this IServiceCollection services, public static IServiceCollection AddConfig(this IServiceCollection services, IConfiguration configuration) where T : class, new() + { + return services.ConfigureWithValidation(options => configuration.Bind(options)); + } + + public static IServiceCollection ConfigureWithValidation(this IServiceCollection services, Action configure) + where T : class, new() { if (services.Any(x => x.ServiceType == typeof(IConfigureOptions))) { @@ -27,7 +34,7 @@ public static IServiceCollection AddConfig(this IServiceCollection services, services.AddTransient(); } - services.Configure(configuration); + services.Configure(configure); services.AddTransient>(); return services; diff --git a/tests/Rtl.Configuration.Validation.Tests/ConfigureWithValidationTests.cs b/tests/Rtl.Configuration.Validation.Tests/ConfigureWithValidationTests.cs new file mode 100644 index 0000000..c2a84fa --- /dev/null +++ b/tests/Rtl.Configuration.Validation.Tests/ConfigureWithValidationTests.cs @@ -0,0 +1,30 @@ +using System; +using System.Threading.Tasks; +using Rtl.Configuration.Validation.Tests.Configs; +using Rtl.Configuration.Validation.Tests.Helpers; +using Xunit; + +namespace Rtl.Configuration.Validation.Tests +{ + public class ConfigureTests + { + [Fact] + public async Task ConfigureWithValidationDoesntThrow() + { + await TestHelpers.ValidationSucceeds(null, services => + services.ConfigureWithValidation(option => + { + option.Name = "asd"; + option.Value = 5; + })); + } + + [Fact] + public void ConfigureWithValidationThrows() + { + TestHelpers.ValidationThrows(null, services => + services.ConfigureWithValidation(option => + option.Name = string.Empty)); + } + } +} \ No newline at end of file diff --git a/tests/Rtl.Configuration.Validation.Tests/Helpers/TestHelpers.cs b/tests/Rtl.Configuration.Validation.Tests/Helpers/TestHelpers.cs index 5e0ce02..6da9614 100644 --- a/tests/Rtl.Configuration.Validation.Tests/Helpers/TestHelpers.cs +++ b/tests/Rtl.Configuration.Validation.Tests/Helpers/TestHelpers.cs @@ -6,6 +6,7 @@ using System.ComponentModel.DataAnnotations; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Rtl.Configuration.Validation.Tests.Helpers @@ -15,19 +16,25 @@ static class TestHelpers public static void ValidationThrows(Dictionary settings, string sectionName = "test") where TConfig : class, new() { - IConfiguration configuration = null; + IConfiguration configuration = new ConfigurationBuilder() + .AddInMemoryCollection(settings) + .Build(); + ValidationThrows(settings, services => services.AddConfig(configuration, sectionName)); + } + + public static void ValidationThrows(Dictionary settings, Action configure) + { Assert.Throws(() => { var webHost = WebHost.CreateDefaultBuilder() .ConfigureAppConfiguration((hostingContext, config) => { config.AddInMemoryCollection(settings); - configuration = config.Build(); }) .ConfigureServices(services => { - services.AddConfig(configuration, sectionName); + configure(services); }) .Configure(app => { @@ -40,21 +47,28 @@ public static void ValidationThrows(Dictionary settings }); } - public static async Task ValidationSucceeds(Dictionary settings, string sectionName = "test") + public static Task ValidationSucceeds(Dictionary settings, string sectionName = "test") where TConfig : class, new() { - IConfiguration configuration = null; + IConfiguration configuration = new ConfigurationBuilder() + .AddInMemoryCollection(settings) + .Build(); + + return ValidationSucceeds(settings, services => services.AddConfig(configuration, sectionName)); + } + + public static async Task ValidationSucceeds(Dictionary settings, Action configure) + { using (var cts = new CancellationTokenSource()) { var webHost = WebHost.CreateDefaultBuilder() .ConfigureAppConfiguration((hostingContext, config) => { config.AddInMemoryCollection(settings); - configuration = config.Build(); }) .ConfigureServices(services => { - services.AddConfig(configuration, sectionName); + configure(services); }) .Configure(app => { @@ -67,4 +81,4 @@ public static async Task ValidationSucceeds(Dictionary } } } -} +} \ No newline at end of file