Ух ты, управление временем жизни с помощью Unity в приложении MVC.С чего начать?
Прежде всего, сеансовые синглтоны на самом деле невозможны, поскольку нет системы 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;
}
}