![]() |
VOOZH | about |
dotnet add package OpenFeature.Providers.MultiProvider --version 2.13.0
NuGet\Install-Package OpenFeature.Providers.MultiProvider -Version 2.13.0
<PackageReference Include="OpenFeature.Providers.MultiProvider" Version="2.13.0" />
<PackageVersion Include="OpenFeature.Providers.MultiProvider" Version="2.13.0" />Directory.Packages.props
<PackageReference Include="OpenFeature.Providers.MultiProvider" />Project file
paket add OpenFeature.Providers.MultiProvider --version 2.13.0
#r "nuget: OpenFeature.Providers.MultiProvider, 2.13.0"
#:package OpenFeature.Providers.MultiProvider@2.13.0
#addin nuget:?package=OpenFeature.Providers.MultiProvider&version=2.13.0Install as a Cake Addin
#tool nuget:?package=OpenFeature.Providers.MultiProvider&version=2.13.0Install as a Cake Tool
The MultiProvider is a feature provider that enables the use of multiple underlying providers, allowing different providers to be used for different flag keys or based on specific routing logic. This enables scenarios where different feature flags may be served by different sources or providers within the same application.
The MultiProvider acts as a composite provider that can delegate flag resolution to different underlying providers based on configuration or routing rules. It supports various evaluation strategies to determine how multiple providers should be evaluated and how their results should be combined.
For more information about the MultiProvider specification, see the OpenFeature Multi Provider specification.
dotnet add package OpenFeature.Providers.MultiProvider
The MultiProvider integrates seamlessly with the OpenFeature dependency injection system, allowing you to configure multiple providers using the AddMultiProvider extension method:
using OpenFeature.Providers.MultiProvider.DependencyInjection;
builder.Services.AddOpenFeature(featureBuilder =>
{
featureBuilder
.AddMultiProvider("multi-provider", multiProviderBuilder =>
{
// Add providers using factory methods for proper DI integration
multiProviderBuilder
.AddProvider("primary", sp => new YourPrimaryProvider())
.AddProvider("fallback", sp => new YourFallbackProvider())
.UseStrategy<FirstMatchStrategy>();
});
});
// Retrieve and use the client
var featureClient = openFeatureApi.GetClient("multi-provider");
var result = await featureClient.GetBooleanValueAsync("my-flag", false);
The MultiProviderBuilder provides several methods to add providers:
Using Factory Methods:
multiProviderBuilder
.AddProvider("provider-name", sp => new InMemoryProvider(flags))
.AddProvider("another-provider", sp => sp.GetRequiredService<SomeProvider>());
Using Provider Instances:
var provider = new InMemoryProvider(flags);
multiProviderBuilder.AddProvider("provider-name", provider);
Using Generic Type Resolution:
// Provider will be resolved from DI container
multiProviderBuilder.AddProvider<YourProvider>("provider-name");
// Or with custom factory
multiProviderBuilder.AddProvider<YourProvider>("provider-name", sp => new YourProvider(config));
Specify an evaluation strategy using any of these methods:
// Using generic type
multiProviderBuilder.UseStrategy<FirstMatchStrategy>();
// Using factory method with DI
multiProviderBuilder.UseStrategy(sp => new FirstMatchStrategy());
// Using strategy instance
multiProviderBuilder.UseStrategy(new ComparisonStrategy());
Configure the MultiProvider for a specific domain:
featureBuilder
.AddMultiProvider("production-domain", multiProviderBuilder =>
{
multiProviderBuilder
.AddProvider("remote", sp => new RemoteProvider())
.AddProvider("cache", sp => new CacheProvider())
.UseStrategy<FirstSuccessfulStrategy>();
});
For scenarios where dependency injection is not available, you can use the traditional setup:
using OpenFeature;
using OpenFeature.Providers.MultiProvider;
// Create your individual providers
var primaryProvider = new YourPrimaryProvider();
var fallbackProvider = new YourFallbackProvider();
// Create provider entries
var providerEntries = new[]
{
new ProviderEntry(primaryProvider, "primary"),
new ProviderEntry(fallbackProvider, "fallback")
};
// Create and set the MultiProvider
var multiProvider = new MultiProvider(providerEntries);
await Api.Instance.SetProviderAsync(multiProvider);
// Use the client as normal
var client = Api.Instance.GetClient();
var result = await client.GetBooleanValueAsync("my-flag", false);
The MultiProvider supports several evaluation strategies to determine how providers are evaluated:
Returns the first result that does not indicate "flag not found". Providers are evaluated sequentially in the order they were configured.
using OpenFeature.Providers.MultiProvider.Strategies;
var strategy = new FirstMatchStrategy();
var multiProvider = new MultiProvider(providerEntries, strategy);
Returns the first result that does not result in an error. If any provider returns an error, it's ignored as long as there is a successful result.
using OpenFeature.Providers.MultiProvider.Strategies;
var strategy = new FirstSuccessfulStrategy();
var multiProvider = new MultiProvider(providerEntries, strategy);
Evaluates all providers and compares their results. Useful for testing or validation scenarios where you want to ensure providers return consistent values.
using OpenFeature.Providers.MultiProvider.Strategies;
var strategy = new ComparisonStrategy();
var multiProvider = new MultiProvider(providerEntries, strategy);
You can assign names to providers for better identification and debugging:
var providerEntries = new[]
{
new ProviderEntry(new ProviderA(), "provider-a"),
new ProviderEntry(new ProviderB(), "provider-b"),
new ProviderEntry(new ProviderC(), "provider-c")
};
The MultiProvider respects evaluation context and passes it to underlying providers:
var context = EvaluationContext.Builder()
.Set("userId", "user123")
.Set("environment", "production")
.Build();
var result = await client.GetBooleanValueAsync("feature-flag", false, context);
Use multiple providers with fallback capabilities:
var providerEntries = new[]
{
new ProviderEntry(new RemoteProvider(), "remote"),
new ProviderEntry(new LocalCacheProvider(), "cache"),
new ProviderEntry(new StaticProvider(), "static")
};
var multiProvider = new MultiProvider(providerEntries, new FirstSuccessfulStrategy());
Compare results from different providers for testing purposes:
var providerEntries = new[]
{
new ProviderEntry(new ProviderA(), "provider-a"),
new ProviderEntry(new ProviderB(), "provider-b")
};
var multiProvider = new MultiProvider(providerEntries, new ComparisonStrategy());
Gradually migrate from one provider to another:
var providerEntries = new[]
{
new ProviderEntry(new NewProvider(), "new-provider"),
new ProviderEntry(new LegacyProvider(), "legacy-provider")
};
var multiProvider = new MultiProvider(providerEntries, new FirstMatchStrategy());
The MultiProvider handles errors from underlying providers according to the chosen evaluation strategy:
The MultiProvider is thread-safe and can be used concurrently across multiple threads. It properly handles initialization and shutdown of underlying providers.
The MultiProvider manages the lifecycle of all registered providers:
// Initialize all providers
await multiProvider.InitializeAsync(context);
// Shutdown all providers
await multiProvider.ShutdownAsync();
// Dispose (implements IAsyncDisposable)
await multiProvider.DisposeAsync();
The MultiProvider supports OpenFeature events and provides specification-compliant event handling. It follows the OpenFeature Multi-Provider specification for event handling behavior.
using OpenFeature;
using OpenFeature.Providers.MultiProvider;
// Create the MultiProvider with multiple providers
var providerEntries = new[]
{
new ProviderEntry(new ProviderA(), "provider-a"),
new ProviderEntry(new ProviderB(), "provider-b")
};
var multiProvider = new MultiProvider(providerEntries);
// Subscribe to MultiProvider events
Api.Instance.AddHandler(ProviderEventTypes.ProviderReady, (eventDetails) =>
{
Console.WriteLine($"MultiProvider is ready: {eventDetails?.ProviderName}");
});
Api.Instance.AddHandler(ProviderEventTypes.ProviderStale, (eventDetails) =>
{
Console.WriteLine($"MultiProvider became stale: {eventDetails?.Message}");
});
Api.Instance.AddHandler(ProviderEventTypes.ProviderConfigurationChanged, (eventDetails) =>
{
Console.WriteLine($"Configuration changed - Flags: {string.Join(", ", eventDetails?.FlagsChanged ?? [])}");
});
Api.Instance.AddHandler(ProviderEventTypes.ProviderError, (eventDetails) =>
{
Console.WriteLine($"MultiProvider error: {eventDetails?.Message}");
});
// Set the provider - this will initialize all underlying providers
// and emit PROVIDER_READY when all are successfully initialized
await Api.Instance.SetProviderAsync(multiProvider);
// Later, if an underlying provider becomes stale and changes MultiProvider status:
// Only then will a PROVIDER_STALE event be emitted from MultiProvider
During Initialization:
PROVIDER_READY when all underlying providers initialize successfullyPROVIDER_ERROR if any providers fail to initialize (causing aggregate status to become ERROR/FATAL)Runtime Status Changes:
PROVIDER_STALEConfiguration Changes:
PROVIDER_CONFIGURATION_CHANGED events from underlying providers are always re-emittedSee the for details on how to contribute to this project.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 is compatible. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 is compatible. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
This package is not used by any NuGet packages.
This package is not used by any popular GitHub repositories.