From 31f525f27728975ff8504899303199ed9810683f Mon Sep 17 00:00:00 2001 From: "Lingling Ye (from Dev Box)" Date: Wed, 22 Apr 2026 13:31:31 +0800 Subject: [PATCH] Example app for paramters object --- .../InMemoryFeatureDefinitionProvider.cs | 76 +++++++++++++++++++ .../ParameterObjectConsoleApp.csproj | 19 +++++ examples/ParameterObjectConsoleApp/Program.cs | 40 ++++++++++ examples/ParameterObjectConsoleApp/README.md | 33 ++++++++ 4 files changed, 168 insertions(+) create mode 100644 examples/ParameterObjectConsoleApp/InMemoryFeatureDefinitionProvider.cs create mode 100644 examples/ParameterObjectConsoleApp/ParameterObjectConsoleApp.csproj create mode 100644 examples/ParameterObjectConsoleApp/Program.cs create mode 100644 examples/ParameterObjectConsoleApp/README.md diff --git a/examples/ParameterObjectConsoleApp/InMemoryFeatureDefinitionProvider.cs b/examples/ParameterObjectConsoleApp/InMemoryFeatureDefinitionProvider.cs new file mode 100644 index 00000000..a9fea33f --- /dev/null +++ b/examples/ParameterObjectConsoleApp/InMemoryFeatureDefinitionProvider.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Microsoft.FeatureManagement; +using Microsoft.FeatureManagement.FeatureFilters; +namespace ParameterObjectConsoleApp +{ + /// + /// A custom feature definition provider that supplies targeting filter settings + /// directly using the ParametersObject property, avoiding the need to construct IConfiguration. + /// + public class InMemoryFeatureDefinitionProvider : IFeatureDefinitionProvider + { + private readonly Dictionary _featureDefinitions; + + public InMemoryFeatureDefinitionProvider() + { + // + // Define feature flags with targeting settings. + // This demonstrates supplying filter parameters directly via ParametersObject + // instead of constructing an IConfiguration with key-value pairs. + _featureDefinitions = new Dictionary + { + ["Beta"] = new FeatureDefinition + { + Name = "Beta", + EnabledFor = new List + { + new FeatureFilterConfiguration + { + Name = "Microsoft.Targeting", + ParametersObject = new TargetingFilterSettings + { + Audience = new Audience + { + Users = new List { "Jeff", "Anne" }, + Groups = new List + { + new GroupRollout + { + Name = "Management", + RolloutPercentage = 100 + }, + new GroupRollout + { + Name = "TeamMembers", + RolloutPercentage = 45 + } + }, + DefaultRolloutPercentage = 20 + } + } + } + } + } + }; + } + + public Task GetFeatureDefinitionAsync(string featureName) + { + _featureDefinitions.TryGetValue(featureName, out FeatureDefinition definition); + + return Task.FromResult(definition); + } + + public async IAsyncEnumerable GetAllFeatureDefinitionsAsync() + { + foreach (var definition in _featureDefinitions.Values) + { + yield return definition; + } + + await Task.CompletedTask; + } + } +} diff --git a/examples/ParameterObjectConsoleApp/ParameterObjectConsoleApp.csproj b/examples/ParameterObjectConsoleApp/ParameterObjectConsoleApp.csproj new file mode 100644 index 00000000..d78a4b80 --- /dev/null +++ b/examples/ParameterObjectConsoleApp/ParameterObjectConsoleApp.csproj @@ -0,0 +1,19 @@ + + + + Exe + net8.0 + enable + + + + + + + + + + + + + diff --git a/examples/ParameterObjectConsoleApp/Program.cs b/examples/ParameterObjectConsoleApp/Program.cs new file mode 100644 index 00000000..bcceb259 --- /dev/null +++ b/examples/ParameterObjectConsoleApp/Program.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +using Microsoft.FeatureManagement; +using Microsoft.FeatureManagement.FeatureFilters; +using ParameterObjectConsoleApp; + +// +// Create a feature manager using a custom definition provider +// that supplies targeting filter settings directly via ParametersObject. +var featureManager = new FeatureManager(new InMemoryFeatureDefinitionProvider()) +{ + FeatureFilters = new List { new ContextualTargetingFilter() } +}; + +// +// Simulate evaluating the "Beta" feature for different users +var users = new List<(string UserId, List Groups)> +{ + ("Jeff", new List { "TeamMembers" }), // Targeted by user name + ("Anne", new List { "Management" }), // Targeted by user name + ("Sam", new List { "Management" }), // Targeted by group (100% rollout) + ("Alice", new List { "TeamMembers" }), // May be targeted by group (45% rollout) + ("Bob", new List { "External" }) // Only targeted by default rollout (20%) +}; + +foreach (var (userId, groups) in users) +{ + const string FeatureName = "Beta"; + + var targetingContext = new TargetingContext + { + UserId = userId, + Groups = groups + }; + + bool enabled = await featureManager.IsEnabledAsync(FeatureName, targetingContext); + + Console.WriteLine($"The {FeatureName} feature is {(enabled ? "enabled" : "disabled")} for the user '{userId}'."); +} diff --git a/examples/ParameterObjectConsoleApp/README.md b/examples/ParameterObjectConsoleApp/README.md new file mode 100644 index 00000000..b6405328 --- /dev/null +++ b/examples/ParameterObjectConsoleApp/README.md @@ -0,0 +1,33 @@ +# ParametersObject Console App + +This example demonstrates how to use the `ParametersObject` property on `FeatureFilterConfiguration` to supply filter settings directly from a custom `IFeatureDefinitionProvider`. + +## Overview + +When implementing a custom `IFeatureDefinitionProvider` that sources feature definitions from alternative backends (e.g., databases, REST APIs), you no longer need to construct an `IConfiguration` object to pass filter parameters. Instead, you can assign settings like `TargetingFilterSettings` directly to `ParametersObject`. + +## Key Concept + +```csharp +new FeatureFilterConfiguration +{ + Name = "Microsoft.Targeting", + ParametersObject = new TargetingFilterSettings + { + Audience = new Audience + { + Users = new List { "Jeff", "Anne" }, + Groups = new List { ... }, + DefaultRolloutPercentage = 20 + } + } +} +``` + +This eliminates the need for verbose `IConfiguration` construction with magic string keys. + +## Running + +``` +dotnet run +```