实现一个基于 IConfiguration 的低配版 FeatureFlag

实现一个基于 IConfiguration 的低配版 FeatureFlag

Intro

在我们的应用中,可能有一些配置开关的需求,某些功能是否启用使用一个配置开关,用的时候就打开,不用的时候就关掉,于是基于 .NET Core 的里配置体系写了一个简单的 FeatureFlag,类似于之前的 AppSetting 的扩展 给 IConfiguration 写一个 GetAppSetting 扩展方法

Sample

首先来看一个实现效果:

[HttpGet("[action]")]
[FeatureFlagFilter("Flag1", DefaultValue = true)]
public IActionResult FeatureEnableTest()
{
    return Ok(new
    {
        Time = DateTime.UtcNow
    });
}

[HttpGet("[action]")]
[FeatureFlagFilter("Flag2", DefaultValue = false)]
public IActionResult FeatureDisableTest()
{
    return Ok(new
    {
        Time = DateTime.UtcNow
    });
}

这是两个完全一样的 API,为了测试 featureFilter 的功能

启用的 API 效果就是可以正常访问:

bd29d3d6c4e2f419d3e431553b1e5bb7.png
feature enable

禁用的效果,默认是返回一个 404,如果需要也可以自定义,只需要实现一个接口,注入进去即可

bcb5b80b6441d29fbbd3ea4d3ceb324c.png
feature disable

Implement

实现代码其实也比较简单,分为两部分,一部分是 IConfiguration 的扩展,从配置中获取某个配置开关的值,另外一部分则是 ASP.NET Core 相关的扩展,上面的示例是一个 MVC Filter 的一个示例,比较简单所以我们就直接看代码

IConfiguration 扩展实现代码如下:

public static string FeatureFlagsSectionName = "FeatureFlags";

public static bool TryGetFeatureFlagValue(this IConfiguration configuration, string featureFlagName, out bool featureFlagValue)
{
    featureFlagValue = false;
    var section = configuration.GetSection(FeatureFlagsSectionName);
    if (section.Exists())
    {
        return bool.TryParse(section[featureFlagName], out featureFlagValue);
    }
    return false;
}

public static bool IsFeatureEnabled(this IConfiguration configuration, string featureFlagName, bool defaultValue = false)
{
    if (TryGetFeatureFlagValue(configuration, featureFlagName, out var value))
    {
        return value;
    }
    return defaultValue;
}

上面示例中的 FeatureFlagFilter 是一个 MVC 的 ResourceFilter,实现代码如下:

public interface IFeatureFlagFilterResponseFactory
{
    public Task<IActionResult> GetResponse(ResourceExecutingContext resourceExecutingContext);
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public sealed class FeatureFlagFilterAttribute : Attribute, IAsyncResourceFilter
{
    public bool DefaultValue { get; set; }
    public string FeatureFlagName { get; }
    public FeatureFlagFilterAttribute(string featureFlagName)
    {
        FeatureFlagName = featureFlagName ?? throw new ArgumentNullException(nameof(featureFlagName));
    }

    public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
    {
        var configuration = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();
        if (configuration.IsFeatureEnabled(FeatureFlagName, DefaultValue))
        {
            await next();
        }
        else
        {
            var responseFactory = context.HttpContext.RequestServices
                .GetService<IFeatureFlagFilterResponseFactory>();
            if (responseFactory != null)
            {
                context.Result = await responseFactory.GetResponse(context);
            }
            else
            {
                context.Result = new NotFoundResult();
            }
        }
    }
}

More

关于 FeatherFlag,上面只是一个简单的封装,微软有一个功能更为丰富的库来支持 Microsoft.FeatureManagement.AspNetCore,  源代码在 Github 上有需要的可以参考 https://github.com/microsoft/FeatureManagement-Dotnet

以上示例代码可以从 Github 获取:https://github.com/WeihanLi/WeihanLi.Web.Extensions/blob/dev/samples/WeihanLi.Web.Extensions.Samples/ValuesController.cs

References

  • https://github.com/WeihanLi/WeihanLi.Web.Extensions/blob/dev/samples/WeihanLi.Web.Extensions.Samples/ValuesController.cs

  • https://github.com/WeihanLi/WeihanLi.Web.Extensions/blob/dev/src/WeihanLi.Web.Extensions/Middleware/FeaturedMiddleware.cs

  • https://github.com/WeihanLi/WeihanLi.Common/blob/dev/src/WeihanLi.Common/Extensions/ConfigurationExtension.cs#L131

  • https://github.com/microsoft/FeatureManagement-Dotnet

  • https://www.nuget.org/packages/Microsoft.FeatureManagement.AspNetCore/

  • 给 IConfiguration 写一个 GetAppSetting 扩展方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值