Skip to content
Raúl A. Canales edited this page Jun 8, 2020 · 2 revisions

Table of contents

  1. What is FeatuR?
  2. Installation
  3. Content of the package
  4. First steps
    1. Setup feature data
    2. Instantiate service
    3. Call IsFeatureEnabled
    4. Using Dependency Injection
  5. Main functions
    1. IsFeatureEnabled
    2. GetEnabledFeatures
    3. EvaluateFeatures

What is FeatuR?

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.

Installation

To get started, you should add the FeatuR package to your project:

dotnet package add FeatuR

Content of the package

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 steps

Set up feature data

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>()
   }
});

Instantiate service

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);

Call IsFeatureEnabled

Finally, we could use the service like the following example:

if(service.IsFeatureEnabled("test"))
{
   return Something();
}
else
{
   return SomethingElse();
}

Using Dependency Injection

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();
}

Main functions

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:

IsFeatureEnabled

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();
}

GetEnabledFeatures

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

EvaluateFeatures

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);