Resolve <T>()是否按会话返回对象?

Sam*_*amo 2 c# asp.net-mvc ioc-container unity-container

在Microsoft Unity IoC中,如果我调用Resolve<SomeType>(),我可以保证返回的对象是在当前会话期间创建的对象吗?

例如,三个用户登录,并且假设SomeType在容器中创建的对象具有针对每个用户的不同值.是否会调用Resolve返回为当前用户创建的对象?或者它会做一些愚蠢的事情,比如返回创建的最后一个?

由于一些环境问题,我自己也遇到了麻烦,我需要尽快检查一下,所以如果有人能回答这个问题,那将非常有帮助!

编辑

请原谅我,我是Unity的新手,但根据我在这里阅读的内容,似乎我应该能够在容器中注册具有唯一名称的对象,并通过该名称检索它们.那么,我不能使用会话ID或会话中持续存在的其他值来检索我的对象吗?

Igo*_*aka 6

哦哇,在MVC应用程序中使用Unity的终身管理.我从哪里开始?

首先,会话单例实际上是不可能的,因为没有ASP.NET系统可以保证在同一会话中的请求之间使用相同的实例.会话可以通过在请求之间对其进行序列化和反序列化来模仿会话中持久存在的同一对象.

瞬态实例 - 即没有生命周期管理规范的简单注册在99%的时间内都是足够的.这意味着每次需要时都会创建一个已注册类型的实例.

在请求的整个生命周期中,您很少需要实例.但是当你需要那些时,你真的需要那些.与DB的连接是完美的候选者.另一方面,请求单身人士更容易创建和管理.

最优雅的解决方案是使用Unity的子容器功能.可以在请求开始时创建子容器,在请求结束时处置(作为额外的奖励,它将处理所有ContainerControlledLifetimeManager实例).

创建子容器时,所有注册仍可从父容器中获取,因此您需要在子容器中注册特定于请求的内容.

这是伪代码,使这个工作:

private void Application_Start() {
  _parentContainer = new UnityContainer();
   //creates a transient registration, available at any point in the app.
  _parentContainer.RegisterType<IParentIntf, ParentIntfImpl>();
  ControllerBuilder.Current.SetControllerFactory(new ServiceLocatorControllerFactory());
}

private void Application_BeginRequest() {
  var childContainer = _parentContainer.CreateChildContainer();
  //registers a request "singleton"
  //This registration is a type registration, an instance of RequestInterfaceImpl
  //will be created when needed and then kept in the container for later use.
  childContainer.RegisterType<IRequestInterface,RequestInterfaceImpl>(new ContainerControlledLifetimeManager());
  //save the child container in the context, so we can use it later
  HttpContext.Items["childContainer"] = childContainer;
}

private void Application_EndRequest() {
  //dispose the child container
  ((IUnityContainer)HttpContext.Items["childContainer"]).Dispose();
}
Run Code Online (Sandbox Code Playgroud)

另一件需要做的事情是覆盖Controller Factory以使用子容器来创建控制器.Controller是进入应用程序的第一个入口点,它们可以简单地依赖于构造函数中的其他组件.

public class UnityControllerFactory : DefaultControllerFactory {

    #region IControllerFactory Members

    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName) {
        IController controller;
        controllerName = controllerName.ToLower();
        var container = ((IUnityContainer)HttpContext.Items["childContainer"])
        if(container.IsRegistered<IController>(controllerName))
            controller = container.Resolve<IController>(controllerName);
        else 
            controller = base.CreateController(requestContext, controllerName) ;
        return controller;
    }
} 
Run Code Online (Sandbox Code Playgroud)