Поскольку реализация IoC / DI в MVC 3, скорее всего, в окончательном виде в RC, я ищу обновленную реализацию DependencyResolver, IControllerActivator и IViewPageActivator с использованием Caste Windsor.Есть ли какие-нибудь примеры, которые были обновлены для MVC 3 RC?
EDIT # 1 Реализация средства разрешения зависимостей Виндзора действительно тривиальна, но кое-чего еще не хватает.В отличие от примера Джеффа Путца Ninject (ниже), кажется, что это не так просто, как в случае с Windsor.После установки преобразователя зависимостей следующим образом:
DependencyResolver.SetResolver(new WindsorDependencyResolver(container));
Windsor создает исключение ComponentNotFoundException.Мне нужно предоставить реализации для IControllerFactory и IControllerActivator.Поскольку DefaultControllerFactory поддерживает DependencyResolver, это можно решить следующим образом:
Component.For<IControllerFactory >().ImplementedBy<DefaultControllerFactory>()
Component.For<IControllerActivator >().ImplementedBy<WindsorControllerActivator>(),
WindsorControllerActivator также тривиален.Однако это приводит к другому исключению ComponentNotFoundException для IViewPageActivator.
Это приводит меня к мысли, что я что-то упустил.Нет способа сделать это более сложным, чем реализация фабрики контроллеров и вызов ControllerBuilder.Current.SetControllerFactory в стиле MVC 2.0.
EDIT # 2 Я пропустил тонкую, но важную детальчто распознаватель зависимостей должен возвращать ноль, когда служба не может быть найдена.Реализация выглядит следующим образом:
public class WindsorDependencyResolver : IDependencyResolver
{
private readonly IWindsorContainer container;
public WindsorDependencyResolver(IWindsorContainer container)
{
this.container = container;
}
public object GetService(Type serviceType)
{
return container.Kernel.HasComponent(serviceType) ? container.Resolve(serviceType) : null;
}
public IEnumerable<object> GetServices(Type serviceType)
{
return container.Kernel.HasComponent(serviceType) ? container.ResolveAll(serviceType).Cast<object>() : new object[]{};
}
}
EDIT # 3
Ответ на вопрос в комментариях.Если вы обнаружите, что вам нужен собственный IControllerActivator, вот простая реализация для Windsor:
public class WindsorControllerActivator : IControllerActivator
{
private readonly IWindsorContainer container;
public WindsorControllerActivator(IWindsorContainer container)
{
this.container = container;
}
public IController Create(RequestContext requestContext, Type controllerType)
{
return (IController)container.GetService(controllerType);
}
}
}
Опять же, НЕ необходимо для получения базового DIработа с Windsor и средством разрешения зависимостей MVC3.
EDIT # 4 Основываясь на некоторых дальнейших исследованиях и отзывах, кажется, что традиционная реализация фабрики контроллеров - лучший подход для Windsor и MVC3.Проблема заключается в том, что в интерфейсе IDependencyResolver отсутствует метод освобождения, который может привести к утечкам памяти, если Windsor не удаляет свои компоненты.Это, вероятно, не будет проблемой, если все ваши зависимости будут решены с помощью жизненного цикла PerWebRequest, но все же лучше не рисковать.Вот базовая реализация фабрики контроллеров Windsor для MVC3.
public class WindsorControllerFactory : DefaultControllerFactory
{
private readonly IWindsorContainer container;
public WindsorControllerFactory(IWindsorContainer container)
{
this.container = container;
}
public override void ReleaseController(IController controller)
{
container.Kernel.ReleaseComponent(controller);
}
public override IController CreateController(RequestContext requestContext, string controllerName)
{
var controllerComponentName = controllerName + "Controller";
return container.Kernel.Resolve<IController>(controllerComponentName);
}
}
РЕДАКТИРОВАТЬ # 5 Если вы используете области MVC, вышеуказанная реализация не будет работать для вас.Вам нужно будет зарегистрировать каждый контроллер на основе его полного имени и переопределить GetControllerInstance вместо CreateController:
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType != null)
{
return (IController)container.Kernel.Resolve(controllerType);
}
return null;
}