.NET 应用如何优雅的做功能开关(Feature Flag)

点击上方蓝字关注“汪宇杰博客”

导语

曾经,我们要在应用程序里做功能开关,就避免不了在配置文件里加上一堆 bool 类型的配置项,然后在代码里用 if else 去判断。尽管这种做法是可行的,但我们现在有办法让代码更加整洁,避免成堆的 if else 出现。

.NET 功能管理库

微软为了解决常见的功能开关问题场景,推出了 .NET Core Feature Management 库。它由 Azure 团队发布,并属于 Azure 文档的一部分,但我发现就算在没有 Azure 环境的情况下,它依然可以正常全功能运行

Azure 在此的作用仅仅是用 Azure App Configuration 作为功能开关的数据源,而我们完全可以用本地的 appsettings.json 来替代,避免了购买 Azure 从而落魄街头的风险

安装功能管理库

以我的博客系统为例,我的应用是 ASP.NET MVC / Web API类型的,我需要添加的包为 Microsoft.FeatureManagement.AspNetCore。如果你的应用并非ASP.NET,可以只添加 Microsoft.FeatureManagement

<PackageReference Include="Microsoft.FeatureManagement" Version="2.2.0" />

然后注册到 DI 里去

using Microsoft.FeatureManagement;

public class Startup

{

    public void ConfigureServices(IServiceCollection services)

    {

        services.AddFeatureManagement();

    }

}

添加功能开关配置项

以我的博客系统为例,原先我在 AppSettings p 中有两个bool类型的配置项,现在就可以迁移到名为 FeatureManagement 的新 p 里。

相对应的,在 C# 代码里,去掉原来的项,添加一个新的枚举类型,值的名称对应配置项的名称。

这个枚举类型不是必须的,但非常建议创建枚举,这是为了保证在使用功能开关的时候有强类型支持,避免用string导致哪里名字没改对造成996。

使用功能开关

我们只需从DI里拿到 IFeatureManager 的实例,即可判断功能开关是否打开。例如:

IFeatureManager featureManager;

...

if (await featureManager.IsEnabledAsync(nameof(MyFeatureFlags.FeatureA)))

{

    // 执行代码

}

在 ASP.NET 项目里,最方便的就是通过构造函数获取 IFeatureManager 的实例

public class HomeController : Controller

{

    private readonly IFeatureManager _featureManager;

    public HomeController(IFeatureManager featureManager)

    {

        _featureManager = featureManager;

    }

}

那么问题来了,说好的少写 if else 呢?这个 IsEnabledAsync 不还是得写 if?

其实 Microsoft.FeatureManagement.AspNetCore 这个包包括了 MVC / Web API 项目所需要用到的许多助手功能。可以让我们避免大量的 if else。

在 Controller 级别添加功能开关

还是以我博客系统为例,我的 GraphController 只有在 EnableWebApi 开关打开的时候才响应用户请求,那么本来的 if else 判断现在就可以:

[FeatureGate(FeatureFlags.EnableWebApi)]

// ... 

public class GraphController : ControllerBase 

{

// ...

}

是不是很爽?

在 Action 级别添加功能开关

[FeatureGate(FeatureFlags.EnableAudit)]

public async Task<IActionResult> ClearAuditLogs()

{

    // ...

}

在 View 上添加功能开关

先在 _ViewImports.cshtml 中添加 taghelper 声明。

@addTagHelper *, Microsoft.FeatureManagement.AspNetCore

然后就可以用 <feature> 标签选择性的渲染 HTML 内容了!

<feature name="FeatureA">

    <p>This can only be seen if 'FeatureA' is enabled.</p>

</feature>

对于feature关闭才显示的内容,加个 negate 就好了

<feature name="FeatureA" negate="true">

    <p>This will be shown if 'FeatureA' is disabled.</p>

</feature>

还可用  All, Any 属性控制多个功能开关的显示处理。All 表示列出的功能得全启用才执行,Any 表示列出的功能里任意一个为 true 就可以执行。

<feature name="FeatureA, FeatureB" requirement="All">

    <p>This can only be seen if 'FeatureA' and 'FeatureB' are enabled.</p>

</feature>

<feature name="FeatureA, FeatureB" requirement="Any">

    <p>This can be seen if 'FeatureA', 'FeatureB', or both are enabled.</p>

</feature>

根据功能开关添加 Filter

使用 AddForFeature() 拓展方法

using Microsoft.FeatureManagement.FeatureFilters;

IConfiguration Configuration { get; set;}

public void ConfigureServices(IServiceCollection services)

{

    services.AddMvc(options => {

        options.Filters.AddForFeature<SomeMvcFilter>(nameof(MyFeatureFlags.FeatureA));

    });

}

根据功能开关添加 Middleware

app.UseMiddlewareForFeature<ThirdPartyMiddleware>(nameof(MyFeatureFlags.FeatureA));

或者

app.UseForFeature(featureName, appBuilder => {

    appBuilder.UseMiddleware<T>();

});

小提示

功能开关的配置值更改,无需重启应用程序,修改配置文件后可以热更新,立即生效!

另外,如果你足够有钱,也推荐试试 Azure App Configuration,将你的应用功能开关放在云端统一管理,可以非常方便的针对用户群体配置 A/B,蓝绿测试哦!

参考文档:https://docs.microsoft.com/en-us/azure/azure-app-configuration/use-feature-flags-dotnet-core?WT.mc_id=AZ-MVP-5002809

汪宇杰博客

Azure | .NET | 微软 MVP

无广告,不卖课,做纯粹的技术公众号

喜欢本篇内容请点个在看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/306810.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鼠标右键 移动选定的文件夹到指定位置_iRightMouse:一款免费Mac鼠标右键增强神器...

如果你是多年的Windows用户转到macOS平台&#xff0c;你必定会发现Windows上很多非常方便的鼠标右键菜单在macOS上都是没有的&#xff0c;例如新建txt文档、一键隐藏文件等。而这些快捷功能的缺失也确实会带来一些不便&#xff0c;奇客君发现一款刚刚上线的免费右键增强工具&am…

数据结构——从叶子结点到根节点的全部路径

问题 给定一个二叉树&#xff0c;返回所有从根节点到叶子节点的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode-cn.com/problems/binary-tree-paths 257.二叉树的所有路径 与…

台电x80plus装linux,纤巧却不简单——台电X80 Plus评测

8英寸平板一直是各平板品牌混战厮杀的大战场。“性价比”是这个尺寸平板好坏的最重要关键字。今天就为大家带来台电8英寸X80 Plus平板电脑的评测。X80 Plus是台电8英寸产品中的最新款&#xff0c;采用的是英特尔新一代CherrTrail架构芯片Atom X5 Z8300。HD核显由原来的Gen7升级…

数据结构——二叉树的递归算法

二叉树的结构定义&#xff1a; typedef struct BiNode {TElemType data;struct BiNode *lchild;struct BiNode *rchild; }BiNode,*BiTree;这里包含的递归算法有&#xff1a; 二叉树的先序创建&#xff1b;二叉树的先序中序后序遍历&#xff1b;二叉树的销毁算法&#xff1b;双…

使用BeetleX访问redis服务

BeetleX针对redis访问封了全async/await操作模式&#xff0c;通过它可以更高效地访问redis服务。BeetleX.Redis提供读写分离和多机故意写入处理&#xff0c;同时安全的TLS访问机制&#xff0c;在使用功能上组件支持绝大部分基础指令&#xff0c;并提供json&#xff0c;protobuf…

鸿蒙系统可以替代安卓吗,华为今天发布的鸿蒙系统,到底能不能替代安卓?

对于大部分差友们来说&#xff0c;“开发者大会”这个词一定显得陌生而又遥远&#xff0c;跟普通的产品发布会不一样&#xff0c;他们面向的对象并不是普通的消费者&#xff0c;而是各种程序猿和攻城狮。话又说回来&#xff0c;能开“ 开发者大会”&#xff0c;也说明这个企业已…

android loading封装_我们经常用的Loading动画居然还有这种姿势

背景Loading动画几乎每个Android App中都有。一般在需要用户等待的场景&#xff0c;显示一个Loading动画可以让用户知道App正在加载数据&#xff0c;而不是程序卡死&#xff0c;从而给用户较好的使用体验。同样的道理&#xff0c;当加载的数据为空时显示一个数据为空的视图、在…

数据结构——基于字符串模式匹配算法的病毒感染检测

实验四 基于字符串模式匹配算法的病毒感染检测 【实验目的】 1.掌握字符串的顺序存储表示方法。 2.掌握字符串模式匹配BF算法和KMP算法的实现。 【实验内容】 问题描述 医学研究者最近发现了某些新病毒,通过对这些病毒的分析,得知它们的DNA序列都是环状的。现在研究者已收集了…

WPF 使用 Expression Design 画图导出及使用 Path 画图

WPF 使用 Expression Design 画图导出及使用 Path 画图目录WPF 使用 Expression Design 画图导出及使用 Path 画图一、软件介绍二、Microsoft Expression Design 使用三、微语言和 Path 绘图1、"注释" 图形&#xff08;中括号&#xff09;2、"并行模式" 图…

数据结构——模式匹配kmp算法

暴力算法 //暴力算法 int index(SString S,SString T,int pos) {int ipos,j1;while(i<S[0]&&j<T[0]){if(S[i]T[j]){i;j;}else {ii-j2;j1;}}if(j>T[0])return i-T[0];else return 0;} kmp算法 next[]数组的求法&#xff1a; 例子&#xff1a;abaabcac 模式串…

互联网时代供应链

供应链是指围绕核心企业&#xff0c;从配套零件开始&#xff0c;制成中间产品以及最终产品&#xff0c;最后由销售网络把产品送到消费者手中的、将供应商&#xff0c;制造商&#xff0c;分销商直到最终用户连成一个整体的功能网链结构。供应链管理的经营理念是从消费者的角度&a…

win7 计算器 android,教你巧妙应用Win7计算器和时钟

正文最新的Win7是一种个性化设计极强的操作系统&#xff0c;在许多细节方面都做到了人性化设计。其功能的DIY性非常明显&#xff0c;是XP系统远远不能比的。今天我们要说的是Win7计算器和时钟&#xff0c;除了可以计算和时间之外我们还可以让他们有哪些妙用呢&#xff1f;我们左…

真实经历:整整一年了,他是这样从程序员转型做产品经理的

这是头哥侃码的第224篇原创每年年底&#xff0c;有不少企业都会对一年内辛勤劳作的员工量身定做一些奖项。发个奖杯&#xff0c;给点奖金&#xff0c;让那些没得奖的人看看&#xff0c;咱们公司有多么的关注员工的闪光点&#xff0c;优秀之处。用人所长&#xff0c;容人所短&am…

数据结构—— 基于二叉树的算术表达式求值

实验五 基于二叉树的算术表达式求值 数据结构——中序表达式求值&#xff08;栈实现&#xff09; 实验目的&#xff1a; 1.掌握二叉树的二叉链表存储表示和二叉树的遍历等基本算法。 2.掌握根据中缀表达式创建表达式树的算法 3.掌握基于表达式树的表达式求值算法。 实验内容&a…

数字标牌 android,【浩鑫推出全球首款英特尔方案+Android系统数字标牌播放器】PjTime.COM 新品快讯 Intel...

世界知名迷你准系统领导品牌&#xff0d;浩鑫Shuttle&#xff0c;秉承开拓创新&#xff0c;引领行业发展的传统&#xff0c;此次创造性的推出全球首款采用英特尔硬件方案搭载Android系统的NS01A数字标牌播放器&#xff0c;为整个数字标牌行业贡献了全新的硬件解决方案。英特尔方…

BCVP开发者说第3期:Adnc

沉静岁月&#xff0c;淡忘流年1项目简介AdncAdnc是一个轻量级的.NetCore微服务快速开发框架&#xff0c;同时也可以应用于单体架构系统的开发。框架基于JWT认证授权、集成了一系列微服务配套组件&#xff0c;代码简洁、易上手、学习成本低、开箱即用。    框架前端基于Vue、…

数据结构——二叉树的非递归算法

二叉树的非递归算法 先序遍历非递归算法1 先序遍历非递归算法2 非递归交换左右孩子算法 使用栈来实现二叉树的非递归算法 栈的基本算法 #include<stdio.h> #include<bits/stdc.h> typedef int Status; #define OK 1 #define ERROR 0 #define TRUE 1 #define …

python字符串的表示_Python字符串方法总结

Python字符串方法图示&#xff1a; &#xff08;温馨提示&#xff1a;对图片点右键——在新标签页中打开图片&#xff09;1、index() 定义&#xff1a;查找并返回指定str的索引位置&#xff0c;如果没找到则会抛异常&#xff08;查找的顺序是从左至右&#xff09;可以指定范围&…

Kuma 1.0 GA发布,70多项新功能和改进

喜欢就关注我们吧&#xff01;Kuma 1.0 GA 现已发布&#xff0c;包含了 70 多种新功能和改进。Kuma 是一个现代的通用服务网格控制平面&#xff0c;基于 Envoy 搭建&#xff0c;Envoy 是一个为云原生应用设计的强大的代理软件。Kuma 高效的数据平面和先进的控制平面&#xff0c…

还在犹豫是否迁移.NET5?这几个项目已经上线了!

.NET5正式发布有十多天&#xff0c;博客园、知乎、技术群都讨论的非常热烈。关于项目是否迁移.NET5的话题讨论的尤为热烈&#xff0c;作为.NET十年老司机要告诉你&#xff0c;.NET5的迁移势在必行&#xff0c;当下就是最好的时机&#xff01;犹豫项目是否升级到.NET5的&#xf…