From 8bb24fde5ff6ab2a46b79678f384f8edf3068602 Mon Sep 17 00:00:00 2001 From: Kyle Julian <38759683+kylejuliandev@users.noreply.github.com> Date: Tue, 21 Oct 2025 21:26:45 +0100 Subject: [PATCH 1/2] Fix issue when adding a DefaultNamePolicy * If you add a AddPolicyName without having previously added a Provider, the code will get stuck trying to resolve IFeatureClient Signed-off-by: Kyle Julian <38759683+kylejuliandev@users.noreply.github.com> --- .../OpenFeatureBuilderExtensions.cs | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs b/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs index 52c66c42e..7c76c10c5 100644 --- a/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs +++ b/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs @@ -223,16 +223,42 @@ internal static OpenFeatureBuilder AddPolicyBasedClient(this OpenFeatureBuilder { var policy = provider.GetRequiredService>().Value; var name = policy.DefaultNameSelector(provider); + if (name == null) { - return provider.GetRequiredService(); + return ResolveFeatureClient(provider); } - return provider.GetRequiredKeyedService(name); + + return ResolveFeatureClient(provider, name); }); return builder; } + private static IFeatureClient ResolveFeatureClient(IServiceProvider provider, string? name = null) + { + var api = provider.GetRequiredService(); + var context = provider.GetService(); + FeatureClient client; + if (name == null) + { + client = api.GetClient(); + if (context is not null) + { + client.SetContext(context); + } + return client; + } + + client = api.GetClient(name); + if (context is not null) + { + client.SetContext(context); + } + + return client; + } + /// /// Configures policy name options for OpenFeature using the specified options type. /// From 774be8ee60e1518492e04cd7004041178c89c49d Mon Sep 17 00:00:00 2001 From: Kyle Julian <38759683+kylejuliandev@users.noreply.github.com> Date: Tue, 21 Oct 2025 21:58:49 +0100 Subject: [PATCH 2/2] Address copilot comments and improve unit test coverage Signed-off-by: Kyle Julian <38759683+kylejuliandev@users.noreply.github.com> --- .../OpenFeatureBuilderExtensions.cs | 21 ++---------- .../OpenFeatureBuilderExtensionsTests.cs | 32 ++++++++++++++++++- 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs b/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs index 7c76c10c5..5e3de1bcd 100644 --- a/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs +++ b/src/OpenFeature.Hosting/OpenFeatureBuilderExtensions.cs @@ -223,12 +223,6 @@ internal static OpenFeatureBuilder AddPolicyBasedClient(this OpenFeatureBuilder { var policy = provider.GetRequiredService>().Value; var name = policy.DefaultNameSelector(provider); - - if (name == null) - { - return ResolveFeatureClient(provider); - } - return ResolveFeatureClient(provider, name); }); @@ -238,20 +232,9 @@ internal static OpenFeatureBuilder AddPolicyBasedClient(this OpenFeatureBuilder private static IFeatureClient ResolveFeatureClient(IServiceProvider provider, string? name = null) { var api = provider.GetRequiredService(); + var client = api.GetClient(name); var context = provider.GetService(); - FeatureClient client; - if (name == null) - { - client = api.GetClient(); - if (context is not null) - { - client.SetContext(context); - } - return client; - } - - client = api.GetClient(name); - if (context is not null) + if (context != null) { client.SetContext(context); } diff --git a/test/OpenFeature.Hosting.Tests/OpenFeatureBuilderExtensionsTests.cs b/test/OpenFeature.Hosting.Tests/OpenFeatureBuilderExtensionsTests.cs index 1a284c918..1f2662ee1 100644 --- a/test/OpenFeature.Hosting.Tests/OpenFeatureBuilderExtensionsTests.cs +++ b/test/OpenFeature.Hosting.Tests/OpenFeatureBuilderExtensionsTests.cs @@ -539,7 +539,7 @@ public void AddPolicyBasedClient_AddsScopedFeatureClient() Assert.NotNull(client); } - [Fact(Skip = "Bug due to https://github.com/open-feature/dotnet-sdk/issues/543")] + [Fact] public void AddPolicyBasedClient_WithNoDefaultName_AddsScopedFeatureClient() { // Arrange @@ -559,4 +559,34 @@ public void AddPolicyBasedClient_WithNoDefaultName_AddsScopedFeatureClient() var client = scope.ServiceProvider.GetService(); Assert.NotNull(client); } + + [Fact] + public void AddPolicyBasedClient_WithEvaluationContext() + { + // Arrange + _services.AddSingleton(sp => Api.Instance); + + var context = EvaluationContext.Builder() + .Set("userId", "user-123") + .Build(); + + _services.AddTransient(_ => context); + + _services.AddOptions() + .Configure(options => options.DefaultNameSelector = _ => "default-name"); + + _systemUnderTest.AddProvider("default-name", (_, key) => new NoOpFeatureProvider()); + + // Act + _systemUnderTest.AddPolicyBasedClient(); + + // Assert + using var serviceProvider = _services.BuildServiceProvider(); + using var scope = serviceProvider.CreateScope(); + var client = scope.ServiceProvider.GetService(); + Assert.NotNull(client); + + var actualContext = client.GetContext(); + Assert.Equal(context, actualContext); + } }