首页 文章详情

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

DotNet NB | 214 2021-10-30 15:26 0 0 0
UniSMS (合一短信)

实现一个基于 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 效果就是可以正常访问:

feature enable

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

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 : AttributeIAsyncResourceFilter
{
    public bool DefaultValue { getset; }
    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 扩展方法


推荐阅读:
Kubernetes全栈架构师(Kubeadm高可用安装k8s集群)--学习笔记
.NET 云原生架构师训练营(模块一 架构师与云原生)--学习笔记
.NET Core开发实战(第1课:课程介绍)--学习笔记

点击下方卡片关注DotNet NB

一起交流学习

▲ 点击上方卡片关注DotNet NB,一起交流学习

请在公众号后台


回复 【路线图】获取.NET 2021开发者路线图
回复 【原创内容】获取公众号原创内容
回复 【峰会视频】获取.NET Conf开发者大会视频
回复 【个人简介】获取作者个人简介
回复 【年终总结】获取作者年终总结
回复 加群加入DotNet NB 交流学习群

长按识别下方二维码,或点击阅读原文。和我一起,交流学习,分享心得。


good-icon 0
favorite-icon 0
收藏
回复数量: 0
    暂无评论~~
    Ctrl+Enter