温莎集装箱。 ASP.NET MVC 应用程序中对象的生命周期

Windsor container. Lifetime of objects in ASP.NET MVC application

我有一个新项目,其中 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 继承的所有 classes 的依赖注入。

包含 BaseController。

不会对上述以外的其他 class 进行注入。

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

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

对于上面注册的所有控制器,如果它们在构造函数接口 ISecurityManager 中将被注入 class SecurityManager 的实例。

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

我的想法正确吗?似乎不是,至少因为控制器的 LifestyleTransient() 在我看来很奇怪,而且注入的对象也将是单例。

从下到上:

Lifetime of this SecurityManager is singleton as default value. So after application start we will have only one instance of SecurityManager for all controllers till the end of application execution.

这确实会发生。

It seems that not, at least because LifestyleTransient() for controllers seems to me strange and that injected objects will be singletons too.

控制器是临时的,因为它们持有 HttpContext - 它们具有有关当前用户请求和以下响应的信息。这就是为什么它们是瞬变的而不是单例的——HttpContext 是每个请求的,每次 browser/client 请求时都会创建它。

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

控制器的 Register/Resolve/Release 循环可以通过创建自定义控制器工厂并替换默认值来完成:

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

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

如果 SecurityManager 与身份验证或授权有关,则使用 MVC 默认设置可能更好 Filtering mechanisms like IAuthorizationFilter or AuthorizeAttribute。当然,这可能是数据访问过滤器,将它放在不同的对象中可能是合理的。

我回答你的问题了吗?