Как использовать Windsor для внедрения зависимостей в ActionFilterAttributes
Видя, как NInject может это сделать, а AutoFac может это сделать, я пытаюсь выяснить, как внедрить зависимости в MVC ActionFilters, используя Castle Windsor.
В настоящее время я использую уродливый статический вспомогательный класс IoC для разрешения зависимостей из кода конструктора, например:
public class MyFilterAttribute : ActionFilterAttribute
{
private readonly IUserRepository _userRepository;
public MyFilterAttribute() : this(IoC.Resolve<IUserRepository>()) { }
public MyFilterAttribute(IUserRepository userRepository)
{
_userRepository = userRepository;
}
}
Я хотел бы удалить эту статическую антипаттерн IoC из моих фильтров.
Любые намеки на то, как я поступил бы с Касл Виндзор?
И нет, изменение структуры DI не вариант.
2 ответа
Создайте общий атрибут: MyFilterAttribute, где ctor принимает аргумент Type в качестве аргумента - т.е. что-то вроде этого:
public class MyFilterAttribute : ActionFilterAttribute {
public MyFilterAttribute(Type serviceType) {
this.serviceType = serviceType;
}
public override void OnActionExecuting(FilterExecutingContext c) {
Container.Resolve<IFilterService>(serviceType).OnActionExecuting(c);
// alternatively swap c with some context defined by you
}
// (...) action executed implemented analogously
public Type ServiceType { get { return serviceType; } }
public IWindsorContainer Container { set; get; }
}
Затем используйте тот же подход, что и две статьи, на которые вы ссылаетесь, чтобы взять под контроль то, как вызываются действия, и выполнить ручную инъекцию вашего WindsorContainer в атрибут.
Использование: [MyFilter(typeof(IMyFilterService))]
Ваш реальный фильтр будет в классе, реализующем IMyFilterService, который, в свою очередь, должен реализовать IFilterService, который может выглядеть примерно так:
public interface IFilterService {
void ActionExecuting(ActionExecutingContext c);
void ActionExecuted(ActionExecutedContext c);
}
Таким образом, ваш фильтр даже не будет привязан к ASP.NET MVC, а ваш атрибут - просто часть метаданных - так, как это и должно быть!:-)
Когда мне это понадобилось, я опирался на работу, проделанную другими с Ninject и Windsor, чтобы получить зависимости внедрения свойств от моих ActionFilters.