-
Notifications
You must be signed in to change notification settings - Fork 1
Home
FeatuR is a customizable lightweight library to handle feature activations in your projects, where you can customize the rules (also refered as activation strategies), as well as from where you fetch the feature data, and the evaluation of them.
To get started, you should add the FeatuR package to your project:
dotnet package add FeatuR
This package, includes the basic interfaces and classes, as well as some basic implementations:
- UserIdStrategyHandler: to enable features based on user id
- DefaultStrategyHandler: default strategy, will always return true
- InMemoryFeatureStore: allows us to store our features in memory
- FeatureService: basic implementation for the service. Uses reflection to resolve the strategy handlers.
First, we need to set up our feature data. We could do so by simply creating a list:
var features = new List<Feature>();
features.Add(new Feature
{
Id = "test",
Enabled = true,
ActivationStrategies = new Dictionary<string, Dictionary<string, string>>
{
["default"] = new Dictionary<string, string>()
}
});
Then, we pass the above list to our store, and the store to the service:
var store = new InMemoryFeatureStore(features);
var service = new FeatureService(store);
Finally, we could use the service like the following example:
if(service.IsFeatureEnabled("test"))
{
return Something();
}
else
{
return SomethingElse();
}
For convinence, we recommend to install our extension for dependency injection:
dotnet package add FeatuR.DependencyInjection
It will allow us to have our features in our appsettings.json
files like this:
{
"FeatuR": {
"Features": [
{
"Id": "test",
"Name": "Awesome feature",
"Enabled": "true",
"ActivationStrategies": {
"default": {},
"anotherstrategy": {}
}
},
{
"Id": "test",
"Name": "Awesome feature",
"Enabled": "true",
"ActivationStrategies": {
"default": {},
"anotherstrategy": {}
}
}]
}
}
Then, you just have to use the extension method when building your service collection, like the following example:
public class Program
{
public static async Task Main(string[] args)
=> await WebHost.CreateDefaultBuilder(args)
.ConfigureServices(services => services.AddFeatuR().Build())
.Configure(app =>
{
//Configure the middleware
})
.Build()
.RunAsync();
}
The recommended usage of the package, is by using the interface IFeatureService
, either with the implementation already included in the package, or with your own.
It comes with three different functionalities, with several overloads to support async
calls as well. Those functionalities are:
This function is the simplest. It lets us ask for a specific feature id, and it returns a bool
indicating if the feature is enabled or not.
For example:
if(service.IsFeatureEnabled("test"))
{
return Something();
}
else
{
return SomethingElse();
}
We could go beyond that, and pass a context with extra data, that could be needed to determine if a feature is enabled or not, based on its strategies:
var context = new FeatureContext
{
Parameters = new Dictionary<string, string>
{
["UserId"] = "raulcanales"
}
};
if(service.IsFeatureEnabled("test", context))
{
return Something();
}
In this function, we can pass an instance of a IFeatureContext
, and it will return a IEnumerable<string>
containing all the features enabled for the given context.
For example:
var context = new FeatureContext
{
Parameters = new Dictionary<string, string>
{
["UserId"] = "raulcanales"
}
};
var enabledFeatures = service.GetEnabledFeatures(context); // Contains a list with all the enabled feature ids
This last function, gets in an IEnumerable<string>
containing the feature ids that we would like to check and an instance of IFeatureContext
, and returns back a Dictionary<string, bool>
containing the same feature ids provided as key, and a bool
value indicating wether or not the feature is enabled.
For example:
var context = new FeatureContext();
var featuresToEvaluate = new[]
{
"feature-1",
"feature-2",
"feature-3"
};
var result = service.EvaluateFeatures(featuresToEvaluate, context);