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

这是在安装中执行的简化代码

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()在我看来很奇怪,并且注入的对象也将是单例的。

最佳答案

从下到上:


  此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。当然,这可能是数据访问过滤器,将其放在其他对象中可能是合理的。

我回答了你的问题吗?

09-28 01:53