From 6b536b58f37cdb0c935672d5f5a46de7b3743344 Mon Sep 17 00:00:00 2001 From: Nikita Balabaev Date: Mon, 19 Jul 2021 14:44:57 +0000 Subject: [PATCH] Fix #51171: Eager validation of named options --- .../src/OptionsBuilderExtensions.cs | 2 +- .../src/ValidationHostedService.cs | 2 +- .../Microsoft.Extensions.Hosting/src/ValidatorOptions.cs | 4 ++-- .../tests/UnitTests/OptionsBuilderExtensionsTests.cs | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/OptionsBuilderExtensions.cs b/src/libraries/Microsoft.Extensions.Hosting/src/OptionsBuilderExtensions.cs index 94c8115d1a7b7..d24d54235e699 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/OptionsBuilderExtensions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/OptionsBuilderExtensions.cs @@ -34,7 +34,7 @@ public static class OptionsBuilderExtensions { // This adds an action that resolves the options value to force evaluation // We don't care about the result as duplicates are not important - vo.Validators[typeof(TOptions)] = () => options.Get(optionsBuilder.Name); + vo.Validators[(typeof(TOptions), optionsBuilder.Name)] = () => options.Get(optionsBuilder.Name); }); return optionsBuilder; diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/ValidationHostedService.cs b/src/libraries/Microsoft.Extensions.Hosting/src/ValidationHostedService.cs index 2bfc901a918cf..054dde6d61f14 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/ValidationHostedService.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/ValidationHostedService.cs @@ -13,7 +13,7 @@ namespace Microsoft.Extensions.DependencyInjection { internal sealed class ValidationHostedService : IHostedService { - private readonly IDictionary _validators; + private readonly IDictionary<(Type, string), Action> _validators; public ValidationHostedService(IOptions validatorOptions) { diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/ValidatorOptions.cs b/src/libraries/Microsoft.Extensions.Hosting/src/ValidatorOptions.cs index c71d1ea5f0af8..57998c3f48510 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/src/ValidatorOptions.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/src/ValidatorOptions.cs @@ -8,7 +8,7 @@ namespace Microsoft.Extensions.DependencyInjection { internal sealed class ValidatorOptions { - // Maps each options type to a method that forces its evaluation, e.g. IOptionsMonitor.Get(name) - public IDictionary Validators { get; } = new Dictionary(); + // Maps each pair of a) options type and b) options name to a method that forces its evaluation, e.g. IOptionsMonitor.Get(name) + public IDictionary<(Type optionsType, string optionsName), Action> Validators { get; } = new Dictionary<(Type, string), Action>(); } } diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs index 5155fa46fa9ef..53153ac7f2909 100644 --- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs +++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/OptionsBuilderExtensionsTests.cs @@ -135,14 +135,14 @@ public async Task ValidateOnStart_NamedOptions_ValidatesFailureOnStart() [Fact] [ActiveIssue("https://github.com/dotnet/runtime/issues/34582", TestPlatforms.Windows, TargetFrameworkMonikers.Netcoreapp, TestRuntimes.Mono)] [ActiveIssue("https://github.com/dotnet/runtime/issues/52114", TestPlatforms.iOS | TestPlatforms.tvOS | TestPlatforms.MacCatalyst)] - private async Task ValidateOnStart_AddOptionsMultipleTimesForSameType_LastOneGetsTriggered() + private async Task ValidateOnStart_AddNamedOptionsMultipleTimesForSameType_BothGetTriggered() { bool firstOptionsBuilderTriggered = false; bool secondOptionsBuilderTriggered = false; var hostBuilder = CreateHostBuilder(services => { services.AddOptions("bad_configuration1") - .Configure(o => o.Boolean = false) + .Configure(o => o.Boolean = true) .Validate(o => { firstOptionsBuilderTriggered = true; @@ -175,7 +175,7 @@ private async Task ValidateOnStart_AddOptionsMultipleTimesForSameType_LastOneGet ValidateFailure(error, 2, "Boolean", "Integer"); } - Assert.False(firstOptionsBuilderTriggered); + Assert.True(firstOptionsBuilderTriggered); Assert.True(secondOptionsBuilderTriggered); }