При регистрации класса или объекта в контейнере можно указать объект LifetimeManager, который будет управлять временем жизни экземпляров в контейнере.
Класс LifetimeManager очень простой, в нем всего три метода GetValue, SetValue и RemoveValue, причем последний не используется.
При помещении объекта в контейнер вызывается метод SetValue, а при необходимости получить объект вызывается GetValue и если он вернул null, то создается новый объект.
В библиотеку Microsoft.Practices.Unity входит несколько менеджеров.
TransientLifetimeManager – ничего не сохраняет, GetValue всегда возвращает null, поэтому объект создается каждый раз. Этот менеджер используется по-умолчанию при вызове RegisterType.
ContainerControlledLifetimeManager – сохраняет объект в локальной переменной. Поэтому объект живет столько же, сколько и контейнер. Этот (вернее другой, но с таким же поведением) менеджер используется по-умолчанию при вызове RegisterInstance.
ExternallyControlledLifetimeManager – сохраняет слабую ссылку (WeakReference) на объект. При использовании этого менеджера и вызове RegisterInstance сам вызывающий код должен управлять временем жизни объекта, помещенного в контейнер. Когда используется RegisterType этот менеджер будет выдавать уже существующий экземпляр объекта если он есть.
PerThreadLifetimeManager – сохраняет объекты в ThreadStatic словаре. Таким образом каждый поток в программе будет использовать свой набор объектов.
Для применения Unity в ASP.NET приложениях очень легко реализовать LifetimeManager, который сохраняет объект в контексте или в сессии.
Другие области применения LifetimeManager
В Unity нет возможности регистрации метода создания объектов, но это очень легко исправить с помощью своего LifetimeManager и пары extension-методов.
public class FactoryLifetimeManager<T>: LifetimeManager { Func<T> _factoryMethod; LifetimeManager _baseManager; public FactoryLifetimeManager(Func<T> factoryMethod, LifetimeManager baseManager) { _factoryMethod = factoryMethod; _baseManager = baseManager; } public override object GetValue() { var obj = _baseManager.GetValue(); if (obj == null) { obj = _factoryMethod(); SetValue(obj); } return obj; } public override void RemoveValue() { _baseManager.RemoveValue(); } public override void SetValue(object newValue) { _baseManager.SetValue(newValue); } } public static class UnityFactoryMethodExtensions { public static IUnityContainer RegisterFactory<T>(this IUnityContainer container, Func<T> factoryMethod) { return container.RegisterFactory<T>(factoryMethod, new TransientLifetimeManager()); } public static IUnityContainer RegisterFactory<T>(this IUnityContainer container, Func<T> factoryMethod, LifetimeManager lifetimeManager) { return container.RegisterType<T>(new FactoryLifetimeManager<T>(factoryMethod, lifetimeManager)); } public static IUnityContainer RegisterFactory<T>(this IUnityContainer container, Func<T> factoryMethod, string name) { return container.RegisterFactory<T>(factoryMethod, name, new TransientLifetimeManager()); } public static IUnityContainer RegisterFactory<T>(this IUnityContainer container, Func<T> factoryMethod, string name, LifetimeManager lifetimeManager) { return container.RegisterType<T>(name, new FactoryLifetimeManager<T>(factoryMethod, lifetimeManager)); } }