Skip to content
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

feat: Feature Provider Enhancement - #321 #324

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="8.0.2" />
<PackageVersion Include="System.Collections.Immutable" Version="1.7.1" />
<PackageVersion Include="System.Threading.Channels" Version="6.0.0" />
Expand All @@ -29,7 +30,7 @@
<PackageVersion Include="SpecFlow.xUnit" Version="3.9.74" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="8.0.1" />
<PackageVersion Include="Microsoft.AspNetCore.TestHost" Version="8.0.11" />
</ItemGroup>

<ItemGroup Condition="'$(OS)' == 'Unix'">
Expand Down
7 changes: 7 additions & 0 deletions OpenFeature.sln
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature.DependencyInjec
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenFeature.Hosting", "src\OpenFeature.Hosting\OpenFeature.Hosting.csproj", "{C99DA02A-3981-45A6-B3F8-4A1A48653DEE}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenFeature.IntegrationTests", "test\OpenFeature.IntegrationTests\OpenFeature.IntegrationTests.csproj", "{68463B47-36B4-8DB5-5D02-662C169E85B0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -119,6 +121,10 @@ Global
{C99DA02A-3981-45A6-B3F8-4A1A48653DEE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C99DA02A-3981-45A6-B3F8-4A1A48653DEE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C99DA02A-3981-45A6-B3F8-4A1A48653DEE}.Release|Any CPU.Build.0 = Release|Any CPU
{68463B47-36B4-8DB5-5D02-662C169E85B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{68463B47-36B4-8DB5-5D02-662C169E85B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{68463B47-36B4-8DB5-5D02-662C169E85B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{68463B47-36B4-8DB5-5D02-662C169E85B0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -137,6 +143,7 @@ Global
{C5415057-2700-48B5-940A-7A10969FA639} = {C97E9975-E10A-4817-AE2C-4DD69C3C02D4}
{EB35F9F6-8A79-410E-A293-9387BC4AC9A7} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
{C99DA02A-3981-45A6-B3F8-4A1A48653DEE} = {C97E9975-E10A-4817-AE2C-4DD69C3C02D4}
{68463B47-36B4-8DB5-5D02-662C169E85B0} = {65FBA159-23E0-4CF9-881B-F78DBFF198E9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {41F01B78-FB06-404F-8AD0-6ED6973F948F}
Expand Down
60 changes: 31 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -338,41 +338,43 @@ builder.Services.AddOpenFeature(featureBuilder => {
});
});
```
#### Creating a New Provider
To integrate a custom provider, such as InMemoryProvider, you’ll need to create a factory that builds and configures the provider. This section demonstrates how to set up InMemoryProvider as a new provider with custom configuration options.

**Configuring InMemoryProvider as a New Provider**
<br />Begin by creating a custom factory class, `InMemoryProviderFactory`, that implements `IFeatureProviderFactory`. This factory will initialize your provider with any necessary configurations.
```csharp
public class InMemoryProviderFactory : IFeatureProviderFactory
{
internal IDictionary<string, Flag>? Flags { get; set; }

public FeatureProvider Create() => new InMemoryProvider(Flags);
}
```
**Adding an Extension Method to OpenFeatureBuilder**
<br />To streamline the configuration process, add an extension method, `AddInMemoryProvider`, to `OpenFeatureBuilder`. This allows you to set up the provider with either a domain-scoped or a default configuration.
### Registering a Custom Provider
You can register a custom provider, such as `InMemoryProvider`, with OpenFeature using the `AddProvider` method. This approach allows you to dynamically resolve services or configurations during registration.

```csharp
public static partial class FeatureBuilderExtensions
{
public static OpenFeatureBuilder AddInMemoryProvider(this OpenFeatureBuilder builder, Action<IDictionary<string, Flag>>? configure = null)
=> builder.AddProvider<InMemoryProviderFactory>(factory => ConfigureFlags(factory, configure));
services.AddOpenFeature()
.AddProvider(provider =>
{
// Resolve services or configurations as needed
var configuration = provider.GetRequiredService<IConfiguration>();
var flags = new Dictionary<string, Flag>
{
{ "feature-key", new Flag<bool>(configuration.GetValue<bool>("FeatureFlags:Key")) }
};

// Register a custom provider, such as InMemoryProvider
return new InMemoryProvider(flags);
});
```

public static OpenFeatureBuilder AddInMemoryProvider(this OpenFeatureBuilder builder, string domain, Action<IDictionary<string, Flag>>? configure = null)
=> builder.AddProvider<InMemoryProviderFactory>(domain, factory => ConfigureFlags(factory, configure));
#### Adding a Domain-Scoped Provider

private static void ConfigureFlags(InMemoryProviderFactory factory, Action<IDictionary<string, Flag>>? configure)
{
if (configure == null)
return;
You can also register a domain-scoped custom provider, enabling configurations specific to each domain:

var flag = new Dictionary<string, Flag>();
configure.Invoke(flag);
factory.Flags = flag;
}
}
```csharp
services.AddOpenFeature()
.AddProvider("my-domain", (provider, domain) =>
{
// Resolve services or configurations as needed for the domain
var flags = new Dictionary<string, Flag>
{
{ $"{domain}-feature-key", new Flag<bool>(true) }
};

// Register a domain-scoped custom provider such as InMemoryProvider
return new InMemoryProvider(flags);
});
```

<!-- x-hide-in-docs-start -->
Expand Down
23 changes: 0 additions & 23 deletions src/OpenFeature.DependencyInjection/IFeatureProviderFactory.cs

This file was deleted.

Loading
Loading