Согласно документации , у вас есть несколько вариантов здесь:
Если ваши фильтры имеют зависимости, к которым вам нужен доступ из DI, есть несколько поддерживаемых подходов.Вы можете применить свой фильтр к классу или методу действия, используя одно из следующих действий:
Атрибуты ServiceFilter или TypeFilter
Если вы просто хотите, чтобы это работало быстроВы можете просто использовать одну из первых двух опций, чтобы применить свой фильтр к контроллеру или действию контроллера.При этом ваш фильтр не обязательно должен быть атрибутом:
[TypeFilter(typeof(ExampleActionFilter))]
public IActionResult Example()
=> View();
ExampleActionFilter
может просто реализовать, например, IAsyncActionFilter
, и вы можете напрямую зависеть от вещей, использующихВнедрение в конструктор:
public class ExampleActionFilter : IAsyncActionFilter
{
private readonly IMemoryCache _memoryCache;
public ExampleActionFilter(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{ … }
}
Вместо этого вы также можете использовать атрибут [ServiceFilter]
, чтобы получить тот же эффект, но тогда вам также потребуется зарегистрировать ваш ExampleActionFilter
в контейнере для внедрения зависимостей в Startup
.
Фабрика фильтров
Если вам нужна большая гибкость, вы можете создать собственную фабрику фильтров.Это позволяет вам написать заводской код для создания фактического экземпляра фильтра самостоятельно.Возможная реализация описанного выше ExampleActionFilter
может выглядеть следующим образом:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class ExampleActionFilterAttribute : Attribute, IFilterFactory
{
public bool IsReusable => false;
public IFilterMetadata CreateInstance(IServiceProvider serviceProvider)
{
return serviceProvider.GetService<ExampleActionFilter>();
}
}
Затем вы можете использовать этот атрибут [ExampleActionFilter]
, чтобы инфраструктура MVC создала для вас экземпляр ExampleActionFilter
, используяКонтейнер DI.
Обратите внимание, что эта реализация в основном то же, что и ServiceFilterAttribute
.Просто его реализация позволяет избежать необходимости использовать ServiceFilterAttribute
напрямую и позволяет вам иметь собственный атрибут.
Использование сервисного локатора
Наконец, есть еще один быстрый вариант, который позволяет вамполностью избегайте инъекций в конструктор.При этом используется шаблон поиска служб для динамического разрешения служб, когда ваш фильтр действительно работает.Поэтому вместо введения зависимости и ее непосредственного использования вы извлекаете ее явно из контекста:
public class ExampleActionFilter : ActionFilterAttribute
{
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
var memoryCache = context.HttpContext.RequestServices.GetService<IMemoryCache>();
// …
}
}