Пакеты интеграции Simple Injector Web API не содержат функции интеграции для фильтров действий, как пакет интеграции Ninject. Но такую интеграцию можно построить в несколько строк кода.
Здесь есть несколько вариантов. Первый вариант - вернуться к разрешению служб непосредственно из вашего фильтра действий, как показано в документации . Этот подход хорош, когда у вас есть один класс фильтра, но это не самый чистый подход, и он заставит вас внести изменения в уже созданный атрибут фильтра.
Таким образом, в качестве второго варианта вы можете создать прокси-класс фильтра действий, который может перенаправить вызов вашему реальному классу фильтра, который затем может быть разрешен Simple Injector:
public class ActionFilterProxy<T> : IActionFilter
where T : IActionFilter
{
public ActionFilterProxy(Container container) => _container = container;
public void OnActionExecuting(ActionExecutingContext filterContext) =>
_container.GetInstance<T>().OnActionExecuting(filterContext);
public void OnActionExecuted(ActionExecutedContext filterContext) =>
_container.GetInstance<T>().OnActionExecuted(filterContext);
}
Используя этот прокси, вы можете выполнить следующую конфигурацию:
GlobalConfiguration.Configuration.Filters.Add(
new ActionFilterProxy<RequiresAtLeastOneOfUserTypesFilter>(container));
container.Register<RequiresAtLeastOneOfUserTypesFilter>();
Это все еще заставляет вас внести изменения в RequiresAtLeastOneOfUserTypesFilter
, потому что Simple Injector не может предоставить информацию об атрибуте (UserType[]
) конструктору RequiresAtLeastOneOfUserTypesFilter
. Вместо этого вы можете изменить RequiresAtLeastOneOfUserTypesFilter
на следующее:
public class RequiresAtLeastOneOfUserTypesFilter : IActionFilter
{
private readonly IUser _user;
public RequiresAtLeastOneOfUserTypesFilter(IUser user) => _user = user;
public void OnActionExecuting(ActionExecutingContext filterContext)
{
// Get the attribute from the controller here
var attribute = filterContext.ActionDescriptor.ControllerDescriptor
.GetCustomAttribute<RequiresAtLeastOneOfUserTypesAttribute>();
bool authorized = _user.HasAtLeastOneOfTypes(attribute.TypesToBeVerified);
if (!authorized)
{
throw new ForbiddenUserException();
}
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
}
}
Третий вариант, который можно использовать, - это тот, который упоминается в документации , который описан в этом блоге post , в котором обсуждается модель, в которой вы размещаете свои фильтры за абстракцией c, специфичной для приложения, и позволяете им автоматически регистрироваться. Он использует аналогичный прокси-подход. Этот метод полезен, когда у вас есть несколько / много фильтров, которые необходимо применить (где их порядок выполнения не имеет значения).