/// <summary> /// Отменяет регистрацию компонента /// </summary> /// <param name="component"> компонент, который должен быть убран из контейнера </param> /// <remarks> /// <note>Очевидно что, такой метод обязан присутствовать в интерфейсе контейнера, однако его использование в задачах помимо тестирования, /// обозначает недостатки архитектуры приложения, так как в нормальном варианте использования контейнер меняет свое поведение по принципу наращивания /// обслуживаемых классов и компонентов, тогда как удаление части компонент может привести к неожиданным эффектам в случае кэширования более /// ранеей выдвачи клиентской стороной</note> /// </remarks> public void Unregister(IComponentDefinition component) { lock (this) { if (null == component) { return; } if (!Components.Contains(component)) { return; } Components.Remove(component); ByTypeCache[component.ServiceType].Remove(component); if (component.Name.IsNotEmpty()) { ByNameCache[component.Name].Remove(component); } foreach (var componentDefinition in OutgoingCache.ToArray()) { if (Equals(componentDefinition.Value, component)) { DropObject(componentDefinition.Key); OutgoingCache.Remove(componentDefinition.Key); } } if (Lifestyle.PerThread == component.Lifestyle) { foreach (var threadCache in ThreadOutgoingCache.ToArray()) { foreach (var componentDefinition in threadCache.Value.ToArray()) { if (Equals(componentDefinition.Value, component)) { DropObject(componentDefinition.Key); OutgoingCache.Remove(componentDefinition.Key); } } } } if (Lifestyle.Pooled == component.Lifestyle) { if (Pool.ContainsKey(component)) { foreach (var obj in Pool[component]) { DropObject(obj); } Pool.Remove(component); } } // hook for extensions - UnRegisterComponent extensions can do something after it's // native unregistration ProcessExtensions(new ContainerContext { Operation = ContainerOperation.UnregisterComponent, Component = component }); } }
/// <summary> /// Возвращает объект контейнеру /// </summary> /// <param name="obj"> Объект, ранее созданнй контейнером </param> /// <remarks> /// <invariant>Метод позволяет контейнеру высвобождать собственные ресурсы и вызывает /// <see cref="IContainerBound.OnContainerRelease" /> /// метод, /// работает это только для /// <see cref="Lifestyle.Pooled" /> /// и /// <see cref="Lifestyle.PerThread" /> /// , для остальных данный метод игнорируется</invariant> /// </remarks> public void Release(object obj) { lock (this) { if (!OutgoingCache.ContainsKey(obj)) { return; } var component = OutgoingCache[obj]; switch (component.Lifestyle) { case Lifestyle.Extension: //extensions not must be released goto case Lifestyle.Transient; case Lifestyle.Default: // default is transient goto case Lifestyle.Transient; case Lifestyle.Transient: //transient not have to be released return; case Lifestyle.Pooled: // pool ion release not disposed, but moved to pool if (!Pool.ContainsKey(component)) { Pool[component] = new Stack <object>(); } Pool[component].Push(obj); break; case Lifestyle.PerThread: //per thread removed from thread cache and OnContainerRelease called //and it can be released only in calling thread if (!ThreadOutgoingCache.ContainsKey(Thread.CurrentThread)) { throw new ContainerException("try to realease thread object from not configured thread"); } if (!ThreadOutgoingCache[Thread.CurrentThread].ContainsKey(obj)) { throw new ContainerException("try to release thread object on not it's thread"); } ThreadOutgoingCache[Thread.CurrentThread].Remove(obj); DropObject(obj); break; case Lifestyle.Singleton: //singletons cannot be released - they will still alive return; } OutgoingCache.Remove(obj); } }