-
Notifications
You must be signed in to change notification settings - Fork 25
feat: Add Dependency Injection and Hosting support for OpenFeature #310
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
toddbaert
merged 1 commit into
open-feature:main
from
arttonoyan:add-dependency-injection
Nov 18, 2024
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 38 additions & 0 deletions
38
src/OpenFeature.DependencyInjection/Diagnostics/FeatureCodes.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| namespace OpenFeature.DependencyInjection.Diagnostics; | ||
|
|
||
| /// <summary> | ||
| /// Contains identifiers for experimental features and diagnostics in the OpenFeature framework. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// <c>Experimental</c> - This class includes identifiers that allow developers to track and conditionally enable | ||
| /// experimental features. Each identifier follows a structured code format to indicate the feature domain, | ||
| /// maturity level, and unique identifier. Note that experimental features are subject to change or removal | ||
| /// in future releases. | ||
| /// <para> | ||
| /// <strong>Basic Information</strong><br/> | ||
| /// These identifiers conform to OpenFeature’s Diagnostics Specifications, allowing developers to recognize | ||
| /// and manage experimental features effectively. | ||
| /// </para> | ||
| /// </remarks> | ||
| /// <example> | ||
| /// <code> | ||
| /// Code Structure: | ||
| /// - "OF" - Represents the OpenFeature library. | ||
| /// - "DI" - Indicates the Dependency Injection domain. | ||
| /// - "001" - Unique identifier for a specific feature. | ||
| /// </code> | ||
| /// </example> | ||
| internal static class FeatureCodes | ||
| { | ||
| /// <summary> | ||
| /// Identifier for the experimental Dependency Injection features within the OpenFeature framework. | ||
| /// </summary> | ||
| /// <remarks> | ||
| /// <c>OFDI001</c> identifier marks experimental features in the Dependency Injection (DI) domain. | ||
| /// | ||
| /// Usage: | ||
| /// Developers can use this identifier to conditionally enable or test experimental DI features. | ||
| /// It is part of the OpenFeature diagnostics system to help track experimental functionality. | ||
| /// </remarks> | ||
| public const string NewDi = "OFDI001"; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| using System.Diagnostics; | ||
| using System.Runtime.CompilerServices; | ||
|
|
||
| namespace OpenFeature.DependencyInjection; | ||
|
|
||
| [DebuggerStepThrough] | ||
| internal static class Guard | ||
| { | ||
| public static void ThrowIfNull(object? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) | ||
| { | ||
| if (argument is null) | ||
| throw new ArgumentNullException(paramName); | ||
| } | ||
|
|
||
| public static void ThrowIfNullOrWhiteSpace(string? argument, [CallerArgumentExpression(nameof(argument))] string? paramName = null) | ||
| { | ||
| if (string.IsNullOrWhiteSpace(argument)) | ||
| throw new ArgumentNullException(paramName); | ||
| } | ||
| } |
24 changes: 24 additions & 0 deletions
24
src/OpenFeature.DependencyInjection/IFeatureLifecycleManager.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| namespace OpenFeature.DependencyInjection; | ||
|
|
||
| /// <summary> | ||
| /// Defines the contract for managing the lifecycle of a feature api. | ||
| /// </summary> | ||
| public interface IFeatureLifecycleManager | ||
| { | ||
| /// <summary> | ||
| /// Ensures that the feature provider is properly initialized and ready to be used. | ||
| /// This method should handle all necessary checks, configuration, and setup required to prepare the feature provider. | ||
| /// </summary> | ||
| /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> | ||
| /// <returns>A Task representing the asynchronous operation of initializing the feature provider.</returns> | ||
| /// <exception cref="InvalidOperationException">Thrown when the feature provider is not registered or is in an invalid state.</exception> | ||
| ValueTask EnsureInitializedAsync(CancellationToken cancellationToken = default); | ||
|
|
||
| /// <summary> | ||
| /// Gracefully shuts down the feature api, ensuring all resources are properly disposed of and any persistent state is saved. | ||
| /// This method should handle all necessary cleanup and shutdown operations for the feature provider. | ||
| /// </summary> | ||
| /// <param name="cancellationToken">Propagates notification that operations should be canceled.</param> | ||
| /// <returns>A Task representing the asynchronous operation of shutting down the feature provider.</returns> | ||
| ValueTask ShutdownAsync(CancellationToken cancellationToken = default); | ||
| } |
23 changes: 23 additions & 0 deletions
23
src/OpenFeature.DependencyInjection/IFeatureProviderFactory.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| namespace OpenFeature.DependencyInjection; | ||
|
|
||
| /// <summary> | ||
| /// Provides a contract for creating instances of <see cref="FeatureProvider"/>. | ||
| /// This factory interface enables custom configuration and initialization of feature providers | ||
| /// to support domain-specific or application-specific feature flag management. | ||
| /// </summary> | ||
| #if NET8_0_OR_GREATER | ||
| [System.Diagnostics.CodeAnalysis.Experimental(Diagnostics.FeatureCodes.NewDi)] | ||
| #endif | ||
| public interface IFeatureProviderFactory | ||
| { | ||
| /// <summary> | ||
| /// Creates an instance of a <see cref="FeatureProvider"/> configured according to | ||
| /// the specific settings implemented by the concrete factory. | ||
| /// </summary> | ||
| /// <returns> | ||
| /// A new instance of <see cref="FeatureProvider"/>. | ||
| /// The configuration and behavior of this provider instance are determined by | ||
| /// the implementation of this method. | ||
| /// </returns> | ||
| FeatureProvider Create(); | ||
| } |
51 changes: 51 additions & 0 deletions
51
src/OpenFeature.DependencyInjection/Internal/FeatureLifecycleManager.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using Microsoft.Extensions.Logging; | ||
| using Microsoft.Extensions.Options; | ||
|
|
||
| namespace OpenFeature.DependencyInjection.Internal; | ||
|
|
||
| internal sealed partial class FeatureLifecycleManager : IFeatureLifecycleManager | ||
| { | ||
| private readonly Api _featureApi; | ||
| private readonly IServiceProvider _serviceProvider; | ||
| private readonly ILogger<FeatureLifecycleManager> _logger; | ||
|
|
||
| public FeatureLifecycleManager(Api featureApi, IServiceProvider serviceProvider, ILogger<FeatureLifecycleManager> logger) | ||
| { | ||
| _featureApi = featureApi; | ||
| _serviceProvider = serviceProvider; | ||
| _logger = logger; | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public async ValueTask EnsureInitializedAsync(CancellationToken cancellationToken = default) | ||
| { | ||
| this.LogStartingInitializationOfFeatureProvider(); | ||
|
|
||
| var options = _serviceProvider.GetRequiredService<IOptions<OpenFeatureOptions>>().Value; | ||
| if (options.HasDefaultProvider) | ||
| { | ||
| var featureProvider = _serviceProvider.GetRequiredService<FeatureProvider>(); | ||
| await _featureApi.SetProviderAsync(featureProvider).ConfigureAwait(false); | ||
| } | ||
|
|
||
| foreach (var name in options.ProviderNames) | ||
| { | ||
| var featureProvider = _serviceProvider.GetRequiredKeyedService<FeatureProvider>(name); | ||
| await _featureApi.SetProviderAsync(name, featureProvider).ConfigureAwait(false); | ||
| } | ||
| } | ||
|
|
||
| /// <inheritdoc /> | ||
| public async ValueTask ShutdownAsync(CancellationToken cancellationToken = default) | ||
| { | ||
| this.LogShuttingDownFeatureProvider(); | ||
| await _featureApi.ShutdownAsync().ConfigureAwait(false); | ||
| } | ||
|
|
||
| [LoggerMessage(200, LogLevel.Information, "Starting initialization of the feature provider")] | ||
| partial void LogStartingInitializationOfFeatureProvider(); | ||
|
|
||
| [LoggerMessage(200, LogLevel.Information, "Shutting down the feature provider")] | ||
| partial void LogShuttingDownFeatureProvider(); | ||
| } |
23 changes: 23 additions & 0 deletions
23
src/OpenFeature.DependencyInjection/MultiTarget/CallerArgumentExpressionAttribute.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| // @formatter:off | ||
| // ReSharper disable All | ||
| #if NETCOREAPP3_0_OR_GREATER | ||
| // https://github.com/dotnet/runtime/issues/96197 | ||
| [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.CallerArgumentExpressionAttribute))] | ||
| #else | ||
| #pragma warning disable | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| namespace System.Runtime.CompilerServices; | ||
|
|
||
| [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] | ||
| internal sealed class CallerArgumentExpressionAttribute : Attribute | ||
| { | ||
| public CallerArgumentExpressionAttribute(string parameterName) | ||
| { | ||
| ParameterName = parameterName; | ||
| } | ||
|
|
||
| public string ParameterName { get; } | ||
| } | ||
| #endif | ||
21 changes: 21 additions & 0 deletions
21
src/OpenFeature.DependencyInjection/MultiTarget/IsExternalInit.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,21 @@ | ||
| // @formatter:off | ||
| // ReSharper disable All | ||
| #if NET5_0_OR_GREATER | ||
| // https://github.com/dotnet/runtime/issues/96197 | ||
| [assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Runtime.CompilerServices.IsExternalInit))] | ||
| #else | ||
| #pragma warning disable | ||
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.ComponentModel; | ||
|
|
||
| namespace System.Runtime.CompilerServices; | ||
|
|
||
| /// <summary> | ||
| /// Reserved to be used by the compiler for tracking metadata. | ||
| /// This class should not be used by developers in source code. | ||
| /// </summary> | ||
| [EditorBrowsable(EditorBrowsableState.Never)] | ||
| static class IsExternalInit { } | ||
| #endif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.