12

I'm using Feature Flags as described here. It works alright, I'm just wondering if the following is really the best way to use them if I want to switch between different service implementations inside ConfigureServices()?

I have the following so far:

using Microsoft.FeatureManagement;

public void ConfigureServices(IServiceCollection services)
{
    services.AddFeatureManagement();

    var sp = services.BuildServiceProvider();
    var featureManager = sp.GetService<IFeatureManager>();

    if (featureManager.IsEnabledAsync("UseServiceB").Result)
    {
        services.AddHostedService<MyServiceB>();
    }
    else
    {
        services.AddHostedService<MyServiceA>();
    }
}

Especially since IFeatureManager only provides an async method to check for a feature, this doesn't feel quite right?!

silent
  • 14,494
  • 4
  • 46
  • 86
  • With my experience with DI, feature and services are two different things. What's stopping you from adding both services without checking if the feature is enabled? EDIT: Didn't notice you are about the implementation part. If you want to make things clean, use an extension method so that ConfigureServices won't become bloated. – jegtugado May 03 '21 at 09:15
  • They are two different implementations of basically the same thing. Only one may ever run at the same time – silent May 03 '21 at 09:18
  • 3
    the configuring code runs at the startup and ensured to be run by only one thread so executing the async methods synchronously should be fine. If you don't like the way you have to write every time you check for a feature being enabled or not, just create an extension method (e.g: `IsEnabled`) on the `IFeatureManager`. – King King May 03 '21 at 10:24

2 Answers2

0

I don't see any better way. I found usefull to create extension method for this:

public static class ConfigurationExtensions
{
    public static bool IsFeatureEnabled(this IConfiguration configuration, string feature)
    {
        var featureServices = new ServiceCollection();
        featureServices.AddFeatureManagement(configuration);
        using var provider = featureServices.BuildServiceProvider();
        var manager = provider.GetRequiredService<IFeatureManager>();

        return manager.IsEnabledAsync(feature).GetAwaiter().GetResult();
    }
}
Jan Muncinsky
  • 4,282
  • 4
  • 22
  • 40
  • Isn't this a bad idea, as you could end up calling BuildServiceProvider() more than once, which can have undesirable consequences? – Ozraptor Aug 09 '23 at 06:26
  • @Ozraptor it's calling `BuildServiceProvider()` on custom instance of `ServiceCollection`, unrelated to the framework core `ServiceCollection`. So there are no undesirable consequences. – Jan Muncinsky Aug 10 '23 at 09:18
  • Jan - ah yes I see, you are correct. – Ozraptor Aug 17 '23 at 03:22
0

I am using .net framework 6.0 and I also used the same way but a bit differently. My code looks like this

public static class ConfigureServiceCollectionExtensions
{
    private static bool IsFeatureEnabled(IServiceCollection services, string feature)
            {
                var provider = services.BuildServiceProvider();
                var featureManager = provider.GetService<IFeatureManager>();
                if (featureManager != null)
                {
                    return featureManager.IsEnabledAsync(feature).GetAwaiter().GetResult();
                }
                return false;
            }
    }
  • Isn't this a bad idea, as you could end up calling BuildServiceProvider() more than once, which can have undesirable consequences? I think this https://stackoverflow.com/questions/70036109/azure-feature-management-on-startup is a better solution? – Ozraptor Aug 09 '23 at 06:38