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

问题描述

由于 MVC 3 中的 IoC/DI 实现很可能是 RC 中的最终形式,我正在寻找使用 Caste Windsor 的 DependencyResolver、IControllerActivator 和 IViewPageActivator 的更新实现.是否有针对 MVC 3 RC 更新的示例?

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?

编辑 #1实现 Windsor 依赖解析器确实很简单,但仍然缺少一些东西.与 Jeff Putz 的 Ninject 示例(如下)相反,它似乎不像 Windsor 那样简单.像这样设置依赖解析器后,

EDIT #1Implementing 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)); 

温莎抛出 ComponentNotFoundException.我需要为 IControllerFactory 和 IControllerActivator 提供实现.由于 DefaultControllerFactory 是 DependencyResolver 感知的,因此可以按如下方式解决:

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 也很简单.但是,这会导致 IViewPageActivator 出现另一个 ComponentNotFoundException.

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

这让我相信我错过了一些东西.没有比实现控制器工厂并调用 ControllerBuilder.Current.SetControllerFactory MVC 2.0 样式更复杂的方法了.

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.

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

EDIT #2I 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[]{};
    }
}

编辑 #3

回答评论中的问题.如果您确实发现需要自己的 IControllerActivator,这里有一个简单的 Windsor 实现:

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);
    }
}

}

同样,这对于使用 Windsor 和 MVC3 依赖项解析器进行基本 DI 操作不是必要的.

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

编辑 #4根据一些进一步的研究和反馈,传统的控制器工厂实现似乎是 Windsor 和 MVC3 的最佳方法.令人担忧的是 IDependencyResolver 接口缺少 release 方法,这可能会导致 Windsor 未处理其组件的内存泄漏.如果您的所有依赖项都通过 PerWebRequest 生命周期解决,这可能不会成为问题,但最好不要冒险.这是 MVC3 的 Windsor 控制器工厂的基本实现.

EDIT #4Based 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);
    }
}

编辑 #5如果您使用的是 MVC 区域,则上述实现将不适合您.您需要根据其全名注册每个控制器,并覆盖 GetControllerInstance 而不是 CreateController:

EDIT #5If 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;
    }

推荐答案

自 Beta 版发布以来,界面没有改变,因此各种框架的所有实现都应该仍然有效.事实是,它的界面并没有那么复杂……您应该能够毫不费力地推出自己的界面.例如,我为 Ninject 做了这个:

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);
    }
}

然后像这样在 global.asax 中连接它:

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));
        ...
    }

请记住,那时您可以免费获得各种好东西,包括控制器的 DI、控制器工厂、动作过滤器和视图基类.

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

明确地说,我不确定您的激活器"是什么,但您可能不需要它们.IDependencyResolver 接口自动处理控制器和视图的更新.

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 的 Castle Windsor 依赖解析器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 21:45