Resolvedor de Dependências do Castelo Windsor para MVC 3
Como a implementação de IoC / DI no MVC 3 provavelmente está em sua forma final no RC, estou procurando uma implementação atualizada dos DependencyResolver, IControllerActivator e IViewPageActivator usando Caste Windsor. Existem exemplos que foram atualizados para o MVC 3 RC?
EDIT # 1 A implementação de um resolvedor de dependências de Windsor é realmente trivial, mas ainda falta algo. Ao contrário do exemplo Ninject de Jeff Putz (abaixo), parece que não é tão simples quanto isso com Windsor. Depois de definir o resolvedor de dependências dessa maneira,
DependencyResolver.SetResolver(new WindsorDependencyResolver(container));
Windsor lança ComponentNotFoundException. Preciso fornecer implementações para IControllerFactory e IControllerActivator. Como o DefaultControllerFactory reconhece o DependencyResolver, isso pode ser resolvido da seguinte maneira:
Component.For<IControllerFactory >().ImplementedBy<DefaultControllerFactory>()
Component.For<IControllerActivator >().ImplementedBy<WindsorControllerActivator>(),
O WindsorControllerActivator também é trivial. No entanto, isso leva a outro ComponentNotFoundException para IViewPageActivator.
Isso me leva a acreditar que estou perdendo alguma coisa. Não há como isso ser mais complicado do que implementar uma fábrica de controladores e chamar ControllerBuilder.Current.SetControllerFactory MVC 2.0-style.
EDIT # 2 Perdi os detalhes sutis, mas importantes, de que o resolvedor de Dependências precisa retornar nulo quando um serviço não pode ser encontrado. A implementação é a seguinte:
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
Respondendo a uma pergunta nos comentários. Se você achar que precisa do seu próprio IControllerActivator, aqui está uma implementação simples para o 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);
}
}
}
Novamente, isso éNÃO necessário obter o DI básico trabalhando com Windsor e o resolvedor de dependência do MVC3.
EDIT # 4 Com base em pesquisas e comentários adicionais, parece que uma implementação tradicional de fábrica de controladores é a melhor abordagem para Windsor e MVC3. A preocupação é que a interface do IDependencyResolver não possua um método de liberação, o que poderia causar vazamentos de memória com o Windsor não descartando seus componentes. Provavelmente, isso não será um problema se todas as suas dependências forem resolvidas com o ciclo de vida do PerWebRequest, mas ainda é melhor não arriscar. Aqui está uma implementação básica de uma fábrica de controladores Windsor para 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);
}
}
EDIT # 5 Se você estiver usando áreas MVC, a implementação acima não funcionará para você. Você precisará registrar cada controlador com base em seu nome completo e substituir GetControllerInstance em vez de CreateController:
protected override IController GetControllerInstance(RequestContext context, Type controllerType)
{
if (controllerType != null)
{
return (IController)container.Kernel.Resolve(controllerType);
}
return null;
}