.net Core 中的自定义属性设置

Custom Attribute settings in .net Core

我正在编写一个非常简单的自定义属性,用于 ASP.net Core 的方法。该属性用于处理指示端点方法为 "switched on or off" 的功能标志,如下所示:

1) 如果启用了某个功能,请允许代码通过该方法并正常执行它。 2) 如果该功能关闭,只需从属性 return 并且不执行

内的方法

我的思路是这样的:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class FeatureFlagAttribute : ActionFilterAttribute
{
    private Dictionary<string, bool> myFeaturesList;
    private readonly string selectedFeature;

    public FeatureFlagAttribute(string featureName)
    {
        selectedFeature = featureName;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var found = myFeaturesList.TryGetValue(selectedFeature, out var result);

        if (!found || !result)
        {
            // dont continue
            context.HttpContext.Response.StatusCode = 403;
        }
    }
}

我需要填充 myFeaturesList 才能工作,但我不想每次使用它时都将它传递给构造函数。最好的配置方法是什么?我正在考虑在属性中设置一个 static 属性,但认为这是一个有点蹩脚的方法,必须有更好的方法。提前致谢!

一种不同的方法,但也许将其移出属性,或许使用静态事件作为 API 挂钩?然后你可以把你想要的字典 where-ever?

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class FeatureFlagAttribute : ActionFilterAttribute
{
    public FeatureFlagAttribute(string featureName)
    {
        selectedFeature = featureName;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (IsActive?.Invoke(selectedFeature) == false)
        {
            // dont continue
            context.HttpContext.Response.StatusCode = 403;
        }
    }
    public static event Func<string, bool> IsActive;
}

(注意静态事件需要注意不要造成内存泄露)


或者,保留现有的,但将字典设为静态(和 thread-protected,等等);然后添加某种 API,例如:

public static void SetFeatureEnabled(string featureName, bool enabled);

调整静态字典。

或者,您可以将 featureNames 的创建提取到可注入服务(注册到 DI)中,并将您的属性用作类型过滤器或与 IFilterFactory.

使用类型过滤器,您可以将属性创建为:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class FeatureFlagAttribute : ActionFilterAttribute
{
    private readonly string _featureName;
    private readonly IFeatureService _featureService;

    public FeatureFlagAttribute(string featureName, IFeatureService featureService)
    {
        _featureName = featureName;
        _featureService = featureService;
    }

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        var features = _featureService.GetMyFeatures();
        var found = features.TryGetValue(_featureName, out var result);

        if (!found || !result)
        {
            // don't continue
            context.HttpContext.Response.StatusCode = 403;
        }
    }
}

在构造函数参数中,featureName保持不变,需要定义到属性中,而featureService会从DI中获取,所以你需要为此注册一个实现在您的初创公司 ConfigureServices().

属性用法随着类型过滤器的不同而略有不同,例如:

[TypeFilter(typeof(FeatureFlagAttribute), Arguments = new object[] { "feature-A" })]
public IActionResult Index()
{
    return View();
}

您可以在文档中阅读更多将依赖项注入过滤器的选项: https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.2#dependency-injection