温莎城堡依赖解析器的MVC 3 [英] Castle Windsor Dependency Resolver for MVC 3

查看:79
本文介绍了温莎城堡依赖解析器的MVC 3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

由于MVC 3的IoC / DI执行是最有可能在RC的最终形式,我在寻找使用种姓温莎更新实施DependencyResolver,IControllerActivator和IViewPageActivator的。是否有已更新为MVC 3 RC?

在那里任何的例子

编辑#1
实施温莎依赖解析器确实微不足道,但还是有一些人失踪。相反,杰夫朴子的Ninject为例(如下图),看来,它不是作为与温莎简单。设置依赖解析器像这样之后,

  DependencyResolver.SetResolver(新WindsorDependencyResolver(集装箱));

温莎抛出ComponentNotFoundException。我需要为IControllerFactory和IControllerActivator实现。由于DefaultControllerFactory是DependencyResolver所知,这是可以解决的,如下所示:

  Component.For< IControllerFactory>()ImplementedBy< D​​efaultControllerFactory>()
Component.For&所述; IControllerActivator方式>()ImplementedBy&所述; WindsorControllerActivator>(),

WindsorControllerActivator是平凡的为好。然而,这导致了另一个ComponentNotFoundException为IViewPageActivator

这使我相信,我失去了一些东西。没有办法,这应该是更复杂的比实施控制器工厂,并呼吁ControllerBuilder.Current.SetControllerFactory MVC 2.0风格的。

编辑#2
我错过了微妙但重要的细节是,依赖解析器需要返回null时,无法找到一个服务。实现如下:

 公共类WindsorDependencyResolver:的IDependencyResolver
{
    私人只读IWindsorContainer容器;    公共WindsorDependencyResolver(IWindsorContainer容器)
    {
        this.container =容器;
    }    公共对象GetService的(类型的serviceType)
    {
        返回container.Kernel.HasComponent(的serviceType)? container.Resolve(的serviceType):空;
    }  公共IEnumerable的<对象> GetServices(类型的serviceType)
    {
        返回container.Kernel.HasComponent(的serviceType)? container.ResolveAll(的serviceType).Cast<对象>():新的对象[] {};
    }
}

编辑#3

应对在评论的问题。如果你发现你需要自己的IControllerActivator,这里简单的实现温莎:

 公共类WindsorControllerActivator:IControllerActivator
{
    私人只读IWindsorContainer容器;    公共WindsorControllerActivator(IWindsorContainer容器)
    {
        this.container =容器;
    }    公众一个IController创建(RequestContext的RequestContext的,类型controllerType)
    {
        回报(一个IController)container.GetService(controllerType);
    }
}

}

再次,这是不会必要得到基本的DI与温莎和MVC3依赖解析器的工作。

编辑#4
基于一些进一步的研究和反馈,似乎是一个传统的控制器工厂实现是温莎和MVC3最好的办法。值得关注的是,该接口的IDependencyResolver缺少释放的方法,这可能导致不温莎处置及其组件的内存泄漏。这可能不会是一个问题,如果你所有的依赖都与PerWebRequest生命周期解决,但它仍然是最好不要抓住这个机会。这里有一个基本的实现温莎控制器工厂MVC3的。

 公共类WindsorControllerFactory:DefaultControllerFactory
{
    私人只读IWindsorContainer容器;    公共WindsorControllerFactory(IWindsorContainer容器)
    {
        this.container =容器;
    }    公共覆盖无效ReleaseController(一个IController控制器)
    {
        container.Kernel.ReleaseComponent(控制器);
    }    公众覆盖一个IController CreateController(RequestContext的的RequestContext,串controllerName)
    {
        VAR controllerComponentName = controllerName +控制器;
        返回container.Kernel.Resolve<一个IController>(controllerComponentName);
    }
}

编辑#5
如果你使用MVC领域,上述实施将不会为你工作。您将需要根据它的全名每个控制器注册,并覆盖GetControllerInstance,而不是CreateController:

 保护覆盖一个IController GetControllerInstance(RequestContext的背景下,类型controllerType)
    {
        如果(controllerType!= NULL)
        {
            回报(一个IController)container.Kernel.Resolve(controllerType);
        }
        返回null;
    }


解决方案

该接口,因为测试版并没有改变,因此所有的实现对各种框架应该仍然工作。而事实是,它不是那么复杂的接口......你应该可以,没有什么麻烦推出自己的。例如,我做这一个Ninject:

 公共类NinjectDependencyResolver:的IDependencyResolver
{
    公共NinjectDependencyResolver(内核的iKernel)
    {
        _KERNEL =内核;
    }    私人只读的iKernel _KERNEL;    公共对象GetService的(类型的serviceType)
    {
        返回_kernel.TryGet(的serviceType);
    }    公共IEnumerable的<对象> GetServices(类型的serviceType)
    {
        返回_kernel.GetAll(的serviceType);
    }
}

然后在这样的Global.asax连线起来:

 私有静态的iKernel _KERNEL;
    公众的iKernel内核
    {
        {返回_KERNEL; }
    }    公共无效的Application_Start()
    {
        _KERNEL =新StandardKernel(新CoreInjectionModule());
        DependencyResolver.SetResolver(新NinjectDependencyResolver(内核));
        ...
    }

记住,你得到各种好吃的东西免费在这一点上,包括DI为控制器,控制器工厂,行动过滤器和视图的基类。

编辑:要清楚,我不知道你的活化剂是的,但你可能并不需要它们。该接口的IDependencyResolver处理控制器和视图自动地的newing行动。

Since the IoC/DI implementation in MVC 3 is most likely in its final form in the RC, I'm looking for an updated implementation of the DependencyResolver, IControllerActivator and IViewPageActivator using Caste Windsor. Are there any examples out there that have been updated for MVC 3 RC?

EDIT #1 Implementing a Windsor dependency resolver is indeed trivial, but there's still something missing. Contrary to Jeff Putz's Ninject example (below), it appears that it's not as simple as that with Windsor. After setting the dependency resolver like so,

DependencyResolver.SetResolver(new WindsorDependencyResolver(container)); 

Windsor throws ComponentNotFoundException. I need to provide implementations for IControllerFactory and IControllerActivator. Since the DefaultControllerFactory is DependencyResolver aware, this can be solved as follows:

Component.For<IControllerFactory >().ImplementedBy<DefaultControllerFactory>()
Component.For<IControllerActivator >().ImplementedBy<WindsorControllerActivator>(),

WindsorControllerActivator is trivial as well. However, this leads to another ComponentNotFoundException for IViewPageActivator.

This leads me to believe that I'm missing something. There is no way that this should be more complicated than an implementing a controller factory and calling ControllerBuilder.Current.SetControllerFactory MVC 2.0-style.

EDIT #2 I missed the subtle but important detail that the Dependency resolver needs to return null when a service cannot be found. The implementation is as follows:

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

Responding to a question in the comments. If you do find that you need your own IControllerActivator, here a simple implementation for 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);
    }
}

}

Again, this is NOT necessary to get basic DI working with Windsor and the MVC3 dependency resolver.

EDIT #4 Based on some further research and feedback, it seems that a traditional controller factory implementation is the best approach for Windsor and MVC3. The concern is that the IDependencyResolver interface lacks a release method, which could cause memory leaks with Windsor not disposing its components. This is probably not going to be an issue if all of your dependencies are resolved with the PerWebRequest lifecycle, but it's still better not to take the chance. Here's a basic implementation of a Windsor controller factory for 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 If you're using MVC areas, the above implementation will not work for you. You will need to register each controller based on its full name, and override GetControllerInstance instead of CreateController:

 protected override IController GetControllerInstance(RequestContext context, Type controllerType)
    {
        if (controllerType != null)
        {
            return (IController)container.Kernel.Resolve(controllerType);
        }
        return null;
    }

解决方案

The interface has not changed since the beta release, so all of the implementations for various frameworks should still work. And the truth is, it's not that complicated of an interface... you should be able to roll your own without much hassle. For example, I did this one for Ninject:

public class NinjectDependencyResolver : IDependencyResolver
{
    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    private readonly IKernel _kernel;

    public object GetService(Type serviceType)
    {
        return _kernel.TryGet(serviceType);
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return _kernel.GetAll(serviceType);
    }
}

Then wire it up in global.asax like this:

    private static IKernel _kernel;
    public IKernel Kernel
    {
        get { return _kernel; }
    }

    public void Application_Start()
    {
        _kernel = new StandardKernel(new CoreInjectionModule());
        DependencyResolver.SetResolver(new NinjectDependencyResolver(Kernel));
        ...
    }

Remember, you get all kinds of goodies for free at that point, including DI for controllers, controller factories, action filters and view base classes.

EDIT: To be clear, I'm not sure what your "activators" are, but you probably don't need them. The IDependencyResolver interface handles the newing-up of controllers and views automagically.

这篇关于温莎城堡依赖解析器的MVC 3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆