Настройки пользовательских атрибутов в .net Core - PullRequest
2 голосов
/ 02 июля 2019

Я пишу очень простой пользовательский атрибут, который будет использоваться с моими методами для ASP.net Core. Атрибут предназначен для обработки флагов объектов, которые указывают, что метод конечной точки «включен или выключен» следующим образом:

1) Если функция включена, разрешите коду перейти к методу и выполнить его как обычно. 2) Если функция выключена, просто вернитесь из атрибута и не выполняйте метод в течение

Я думал что-то вроде этого:

[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, чтобы это работало, НО я не хочу передавать его в конструктор каждый раз, когда он используется. Каков наилучший способ настроить это? Я думал об установке статического свойства в атрибуте, но подумал, что это немного неубедительный подход и что должен быть лучший способ. Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 03 июля 2019

В качестве альтернативы вы можете извлечь создание 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

1 голос
/ 02 июля 2019

Другой подход, но, возможно, уберите его из атрибута, возможно, используя статическое событие в качестве хука API?затем вы можете поместить словарь куда угодно ?

[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;
}

(обратите внимание, что вам нужно быть осторожным со статическими событиями, чтобы не вызвать утечки памяти)


В качестве альтернативы, сохраните то, что у вас есть, но сделайте словарь статичным (и защищенным от потоков и т. Д.);затем добавьте некоторый API, например:

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

, который настраивает статический словарь.

...