feat: Extract minimal DI integration to OpenFeature.Providers.DependencyInjection#596
feat: Extract minimal DI integration to OpenFeature.Providers.DependencyInjection#596arttonoyan wants to merge 30 commits intoopen-feature:mainfrom
Conversation
Introduced a new project, `OpenFeature.DependencyInjection.Abstractions`, to the solution. This project supports dependency injection abstractions and targets multiple frameworks (`netstandard2.0`, `net8.0`, `net9.0`, `net462`) for broad compatibility. Configured the project with the `Microsoft.NET.Sdk` SDK and set the root namespace to `OpenFeature.DependencyInjection.Abstractions`. Added dependencies on `Microsoft.Extensions.DependencyInjection.Abstractions` and `Microsoft.Extensions.Options` to enable DI and options configuration.
Refactored the OpenFeature framework to introduce `OpenFeatureProviderBuilder`, enhancing support for dependency injection and provider management. - Changed namespaces to align with DI abstractions. - Made `FeatureCodes` public for broader accessibility. - Added `InternalsVisibleTo` for testing and project references. - Introduced `OpenFeatureProviderBuilder` for managing providers and policies. - Added extension methods for provider and policy registration. - Refactored `OpenFeatureBuilder` to inherit from `OpenFeatureProviderBuilder`. - Consolidated shared functionality in `OpenFeatureProviderOptions`. - Updated `FeatureBuilderExtensions` and `InMemoryProviderOptions` to use the new abstraction. - Updated tests to reflect new method signatures and hierarchy. - Removed redundant methods and properties, improving code organization. These changes improve maintainability, extensibility, and alignment with modern DI patterns.
Simplified the `AddProvider` API by removing the `TFeatureProvider` generic type parameter and directly using the `FeatureProvider` type. Updated the `TOptions` parameter to ensure it derives from `OpenFeatureProviderOptions`. Added a `<ProjectReference>` to `OpenFeature.csproj` in `OpenFeature.DependencyInjection.Abstractions.csproj`. Updated `OpenFeatureOptions` to `OpenFeatureProviderOptions` in the default name selector policy. Refactored `AddInMemoryProvider` methods to align with the new API. Updated tests in `OpenFeatureBuilderExtensionsTests` to reflect the changes and validate the updated functionality. Performed general code cleanup, including XML documentation updates, to improve clarity and maintain consistency across the codebase.
Refactored `FeatureLifecycleManager` to modularize provider, hook, and handler initialization with new methods: `InitializeProvidersAsync`, `InitializeHooks`, and `InitializeHandlers`. Updated `EnsureInitializedAsync` to use these methods for improved readability and maintainability. Revised `AddInMemoryProvider` in `FeatureBuilderExtensions` to use a generic `FeatureProvider` abstraction. Adjusted `CreateProvider` methods accordingly. Improved code clarity in `FeatureFlagIntegrationTest` by renaming variables for consistency and removing redundant assignments.
Updated FeatureLifecycleManagerTests to replace OpenFeatureOptions with OpenFeatureProviderOptions for configuring feature providers. Added support for hooks and keyed singletons to enhance modularity. Introduced additional feature flag retrieval in FeatureFlagIntegrationTest. Added dependency on OpenFeature.DependencyInjection.Abstractions.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #596 +/- ##
==========================================
+ Coverage 93.21% 93.33% +0.11%
==========================================
Files 69 71 +2
Lines 2994 2985 -9
Branches 359 358 -1
==========================================
- Hits 2791 2786 -5
+ Misses 143 136 -7
- Partials 60 63 +3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
src/OpenFeature.Providers.DependencyInjection/OpenFeatureProviderOptions.cs
Show resolved
Hide resolved
src/OpenFeature.Providers.DependencyInjection/Diagnostics/FeatureCodes.cs
Show resolved
Hide resolved
...Feature.DependencyInjection.Abstractions/OpenFeature.DependencyInjection.Abstractions.csproj
Outdated
Show resolved
Hide resolved
src/OpenFeature.Providers.DependencyInjection/OpenFeatureProviderBuilder.cs
Show resolved
Hide resolved
…hub.com/arttonoyan/dotnet-sdk into feature/di-abstractions-builder-api-587
askpt
left a comment
There was a problem hiding this comment.
Great work! I only added a couple of minor comments.
Please have a chat with @kylejuliandev to try understand the impact on his deprecations efforts. I remember he mentioned a couple of fixes he was working on for the DI and I don't want that effort to get lost during this PR.
src/OpenFeature.Providers.DependencyInjection/OpenFeature.Providers.DependencyInjection.csproj
Show resolved
Hide resolved
src/OpenFeature.Providers.DependencyInjection/OpenFeatureProviderBuilderExtensions.cs
Show resolved
Hide resolved
Co-authored-by: André Silva <2493377+askpt@users.noreply.github.com> Signed-off-by: Artyom Tonoyan <arttonoyan@gmail.com>
Co-authored-by: André Silva <2493377+askpt@users.noreply.github.com> Signed-off-by: Artyom Tonoyan <arttonoyan@gmail.com>
Refactored `OpenFeatureOptions` to `OpenFeatureProviderOptions` to improve clarity and maintainability. Updated all references and test cases to use the new class. Removed inheritance of `OpenFeatureOptions` from `OpenFeatureProviderOptions` and introduced `_hookNames` for managing hook names. Replaced `TestOptions` with `TestProviderOptions` in `OpenFeatureBuilderExtensionsTests`, adding a `SomeFlag` property for more flexible testing. Renamed and updated `OpenFeatureOptionsTests` to `OpenFeatureProviderOptionsTests`. Performed general cleanup, including removing unused namespaces, ensuring consistent naming conventions, and aligning method calls with the new class structure.
@arttonoyan just execute |
Removed `OpenFeature.Hosting.Internal` namespace from `FeatureLifecycleManagerTests.cs` and `OpenFeatureBuilderExtensionsTests.cs` as it is no longer required. Adjusted the placement of `OpenFeature.Providers.DependencyInjection` for consistency and improved readability. These changes streamline imports and enhance maintainability.
|
@askpt @kylejuliandev Could you please do a final review? I’d like to merge this PR. |
|
@arttonoyan Please update this action: https://github.com/open-feature/dotnet-sdk/blob/main/.github/workflows/release.yml. This package needs to be added to generate the security artefacts. |
Signed-off-by: Artyom Tonoyan <arttonoyan@gmail.com>
done: 579ac49 |
src/OpenFeature.Providers.DependencyInjection/OpenFeatureProviderBuilderExtensions.cs
Show resolved
Hide resolved
Introduce cancellation checks in InitializeProvidersAsync to allow prompt operation cancellation. Add null-coalescing operator to ensure OpenFeatureProviderOptions are configured, throwing an InvalidOperationException if not. Improve code readability by adjusting formatting.
Explicitly cast the return type of AddProvider method calls to OpenFeatureBuilder in FeatureBuilderExtensions.cs to ensure type specificity. Updated the ArgumentNullException message for null 'configure' parameter to provide clearer guidance on the need for a valid configuration.
|
@askpt @kylejuliandev I ran into a blocking issue. I tried to avoid any major changes, but it looks like I can’t solve it without doing at least some refactoring. The problem While working on the builder.Services.AddOpenFeature(of => of
.AddProvider(_ => new TestProvider())
.AddHook(_ => new TestHook())
);This fails because:
If I reverse the order, it works: builder.Services.AddOpenFeature(of => of
.AddHook(_ => new TestHook())
.AddProvider(_ => new TestProvider())
);Here For me this is a design problem, because the API becomes order-dependent and confusing. I tried to make I see two options. I’m open to other ideas as well. Option 1. Move
|
Need to have a thought. If this requires another package moving/creation/deprecation we might as well do a v3 like I mentioned in Slack. I kinda prefer Option B also, but moving the code all the time doesn't bring the necessary stability, even if this is still in Experimental phase. I would like to know what will be the consequences for the providers and hooks if we go ahead with option B. Which package should it consume? Then the consumers would just install To finish, I would believe if we go with option B, we would need to do a v3, make the DI not-experimental and this PR will be part of v3. |
Here is an updated version you can paste into the PR with the extra Cons included. @askpt there is also an Option C that lets us continue without any breaking changes. Option C. Make
|
Reordered the configuration of `AddOpenFeature` in `Program.cs` to move `AddInMemoryProvider` after `AddMultiProvider`. This change ensures a specific initialization sequence. Additionally, the order of adding hooks and providers was adjusted to register hooks before providers, potentially affecting execution order and initialization. These changes aim to improve the setup of feature flags and dependency injection.
Signed-off-by: Artyom Tonoyan <artonoyan@servicetitan.com>
|
@arttonoyan This PR has several compilation errors. I will have a look when they get fixed. Which option will you think you will implement for the extraction? If there are any necessary breaking changes please rename the title to |
@askpt As we discussed earlier, there is a breaking change related to Instead, I’ve started working on the next step. extracting This should properly address the breaking change and also make future work easier. It will let us extract things like handlers and hooks into separate projects without causing more breaking changes. I’ll open the PR soon. |
|
I have a follow-up PR arttonoyan#4 that builds on top of this one. Because PR arttonoyan#4 is based on the branch in my fork ( What it adds (high level):
At this stage I’m mainly looking for architecture feedback (layering, component approach, package boundaries), not a full nit-level review yet. |
Important
Update. 2025-11-10
Following the discussion in #596 (comment). the package name in this proposal is updated from
OpenFeature.DependencyInjectiontoOpenFeature.Providers.DependencyInjection. Rationale. clearer scope for provider authors. thinner provider packages. reduced coupling with the SDK.This PR
Extract the minimal, provider-agnostic DI surface into a new package:
OpenFeature.DependencyInjection.Abstractions.This isolates the contracts and lightweight wiring needed to integrate any OpenFeature provider without pulling in a concrete implementation.
Related Issues
Fixes #587
Notes
OpenFeatureOptionsinto a new base options type:OpenFeatureProviderOptions.OpenFeatureOptionsnow inherits fromOpenFeatureProviderOptions.OpenFeatureOptionsnow targetsOpenFeatureProviderOptions.Before (internal)
After (internal)
Impact
OpenFeatureOptions) require updates to targetOpenFeatureProviderOptions.How to test
This is a regression-only refactor.
Expectations