温莎容器。 ASP.NET MVC应用程序中对象的生命周期

时间:2016-12-19 19:50:02

标签: c# asp.net castle-windsor

我有一个新项目,其中Windsor容器用于IoC。

以下是在Install

中执行的简化代码
public void Install(IWindsorContainer container, IConfigurationStore store)
{
    container.Register(Classes.FromThisAssembly().BasedOn<BaseController>().LifestyleTransient(), 
                       Component.For<ISecurityManager>().ImplementedBy<SecurityManager>(), 
                       Component.For<IAccountManager>().ImplementedBy<AccountManager>()
                       ........)
}

我在官方文件中找到的信息不足以详细了解这些内容。

Classes.FromThisAssembly().BasedOn<BaseController>().LifestyleTransient(), 

Register方法中的这一行启用了从我的应用程序中继承BaseController的所有类的依赖注入。

包含BaseController。

不会对上述其他类别进行注射。

我们向容器展示所有控制器类的生命周期将是一个实例。

Component.For<ISecurityManager>().ImplementedBy<SecurityManager>()

对于上面注册的所有控制器,如果他们在构造函数接口中有ISecurityManager,则会注入SecurityManager类的实例。

此SecurityManager的生命周期是单例作为默认值。因此,在应用程序启动之后,我们将只为所有控制器提供一个SecurityManager实例,直到应用程序执行结束。

我的想法是否正确?似乎不是,至少因为控制器的LifestyleTransient()对我来说似乎很奇怪,注入的对象也会是单身。

1 个答案:

答案 0 :(得分:4)

从下到上:

  

此SecurityManager的生命周期是单例作为默认值。因此,在应用程序启动之后,我们将只为所有控制器提供一个SecurityManager实例,直到应用程序执行结束。

确实会发生这种情况。

  

似乎不是,至少因为控制器的LifestyleTransient()在我看来很奇怪,注入的对象也会是单身。

控制器是瞬态的,因为它们持有HttpContext - 它们具有有关当前用户请求和以下响应的信息。这就是为什么它们是瞬态而不是单例--HttpContext是每个请求,它是在每次浏览器/客户端请求时创建的。

因此,为什么控制器的寿命比其他服务更短,这是可以理解的。它在很大程度上取决于应用程序的内部架构。如果其他人有更好的想法 - 我非常愿意学习。

控制器的注册/解析/发布周期可以通过创建自定义控制器工厂并替换默认值来完成:

public class WindsorControllerFactory : DefaultControllerFactory
{
    private readonly IKernel _kernel;

    public WindsorControllerFactory(IKernel kernel)
    {
        _kernel = kernel;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
        {
            throw new HttpException(404, string.Format("The controller for path '{0}' could not be found.", requestContext.HttpContext.Request.Path));
        }

        if (_kernel.GetHandler(controllerType) != null)
        {
            return (IController)_kernel.Resolve(controllerType);
        }
        return base.GetControllerInstance(requestContext, controllerType);
    }

    public override void ReleaseController(IController controller)
    {
        _kernel.ReleaseComponent(controller);
    }
}

并在某处放置:

 container.Register(Component.For<IControllerFactory>().ImplementedBy<WindsorControllerFactory>());

我的控制器也有单例依赖项。通过这种方式,您可以实现管道编程模型 - 您通过一系列对象汇集来自控制器的请求,而不是返回结果。

如果SecurityManager与身份验证或授权有关,最好使用MVC默认Filtering机制,如IAuthorizationFilterAuthorizeAttribute。当然这可能是数据访问过滤器,将它放在不同的对象中可能是合理的。

我是否回答了你的问题?