加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net-mvc – 用于MVC 3的Castle Windsor依赖关系解析器

发布时间:2020-12-15 19:33:20 所属栏目:asp.Net 来源:网络整理
导读:由于MVC 3中的IoC / DI实现最有可能是在RC的最终形式,我正在寻找使用Caste Windsor的DependencyResolver,IControllerActivator和IViewPageActivator的更新实现。有没有为MVC 3 RC更新的任何示例? 编辑#1 实现Windsor依赖解析器确实是微不足道的,但仍有一
由于MVC 3中的IoC / DI实现最有可能是在RC的最终形式,我正在寻找使用Caste Windsor的DependencyResolver,IControllerActivator和IViewPageActivator的更新实现。有没有为MVC 3 RC更新的任何示例?

编辑#1
实现Windsor依赖解析器确实是微不足道的,但仍有一些缺失。与Jeff Putz的Ninject示例(下面)相反,它似乎并不像Windsor那么简单。在设置依赖解析器之后,

DependencyResolver.SetResolver(new WindsorDependencyResolver(container));

Windsor抛出ComponentNotFoundException。我需要提供IControllerFactory和IControllerActivator的实现。由于DefaultControllerFactory是DependencyResolver感知,这可以解决如下:

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

WindsorControllerActivator也是微不足道的。但是,这导致IViewPageActivator的另一个ComponentNotFoundException。

这使我相信,我错过了一些东西。没有办法,这应该比实现一个控制器工厂和调用ControllerBuilder.Current.SetControllerFactory MVC 2.0风格更复杂。

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

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:

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依赖解析器。

编辑#4
基于一些进一步的研究和反馈,似乎传统的控制器工厂实现是Windsor和MVC3的最佳方法。关注的是IDependencyResolver接口缺少一个释放方法,这可能会导致内存泄漏与Windsor不处理其组件。如果所有的依赖项都用PerWebRequest生命周期解决,这可能不会是一个问题,但是最好不要冒险。下面是MVC3的Windsor控制器工厂的基本实现。

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

解决方法

接口自beta版本以来没有改变,所以各种框架的所有实现仍然应该工作。事实是,这不是一个接口的复杂 – 你应该能够自己滚动没有很多麻烦。例如,我为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像这样:

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,控制器工厂,动作过滤器和视图基类。

编辑:要清楚,我不知道你的“激活剂”是什么,但你可能不需要它们。 IDependencyResolver接口自动处理控制器和视图的新建。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读