哦,哇,在MVC应用程序中使用Unity的生命周期管理。我从哪说起呢?
首先,会话单例不是真的可行,因为没有ASP.NET系统可以保证在同一个会话中的请求之间使用同一个实例。会话可以通过在请求之间对其进行序列化和反序列化来模仿会话中保存的同一对象。
瞬态实例 - 即无需生命周期管理规范的简单注册在99%的时间内就足够了。这意味着每次需要时都会创建一个注册类型的实例。
您很少需要实例来贯穿请求的整个生命周期。但是,当你需要那些,你真的需要那些。与数据库的连接是完美的选择。另一方面,请求单身人士更容易创建和管理。
最优雅的解决方案是使用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();
}
需要做的另一件事是重写器厂使用子容器创建控制器。控制器是进入应用程序的第一个入口,它们可以简单地依赖构造函数中的其他组件。
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;
}
}
看起来好像你想使用Unity作为缓存,如果你正在注册一个'钥匙'的实例。这实际上并不是Unity最擅长的\,也可能是您收到的答案令人困惑的原因。 – 2011-01-11 19:22:24
如果你确实使用Unity作为缓存,当你有一个Web服务器场时会发生什么,或者当ASP.Net工作者进程再循环时会发生什么? – 2011-01-11 19:32:31
除了@chibacity说了什么之外,如果你在不同的线程之间共享实例,那么你正打开一个让自己受到伤害的世界。哪个线程为特定的请求提供服务是完全不确定的,并且当您想要访问它时,您需要同步左侧和右侧中心。真的,创造新的对象,如果它需要去数据库旅行并不昂贵。 – 2011-01-11 22:41:54