/// <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); } }
/// <summary> /// Возвращает сервис указанного типа. (прямое указание типа) /// </summary> /// <param name="type"> Тип сервиса </param> /// <param name="ctorArguments"> Параметры для вызова конструктора, если не указано - будет использован конструктор по умолчанию. </param> /// <param name="name"> опциональное имя компонента, если указано - поиск будет производиться только среди с компонентов с указаным именем </param> /// <returns> Сервис указанного типа или <c>null</c> , если подходящий компонент не обнаружен </returns> /// <exception cref="ContainerException">При ошибках в конструировании объектов</exception> public object Get(Type type, string name = null, params object[] ctorArguments) { lock (this) { type = type ?? typeof(object); if (type.IsValueType) { throw new ArgumentException("type must be interface or reference type"); } var preresolved = PreResolveWithSubResolvers(type, name, ctorArguments); if (null != preresolved) { return(preresolved); } var component = FindComponent(type, name); if (null == component) { var postresolved = PostResolveWithSubResolvers(type, name, (object[])ctorArguments); if (postresolved != null) { return(postresolved); } if (ThrowErrorOnNotExistedComponent) { throw new ContainerException(string.Format("cannot find component for {0} {1}", type, name)); } return(null); } component.ActivationCount++; object result = null; switch (component.Lifestyle) { case Lifestyle.Default: goto case Lifestyle.Transient; case Lifestyle.Extension: if (null != component.Implementation) { result = component.Implementation; break; } result = CreateInstance(component, ctorArguments); if (component.CacheInstanceOfExtension) { component.Implementation = result; } break; case Lifestyle.Transient: result = CreateInstance(component, ctorArguments); break; case Lifestyle.Pooled: if (Pool.ContainsKey(component) && Pool[component].Count != 0) { result = Pool[component].Pop(); } else { result = CreateInstance(component, ctorArguments); } OutgoingCache[result] = component; break; case Lifestyle.PerThread: if (!ThreadOutgoingCache.ContainsKey(Thread.CurrentThread)) { ThreadOutgoingCache[Thread.CurrentThread] = new Dictionary <object, IComponentDefinition>(); } if (ThreadOutgoingCache[Thread.CurrentThread].ContainsValue(component)) { result = ThreadOutgoingCache[Thread.CurrentThread].First(x => Equals(x.Value, component)).Key; } else { result = CreateInstance(component, ctorArguments); ThreadOutgoingCache[Thread.CurrentThread][result] = component; } OutgoingCache[result] = component; break; case Lifestyle.Singleton: if (null == component.Implementation) { component.Implementation = CreateInstance(component, ctorArguments); if (null != component.LinkedSingletons) { foreach (var linkedSingleton in component.LinkedSingletons) { if (null == linkedSingleton.Implementation) { linkedSingleton.Implementation = component.Implementation; } } } } result = component.Implementation; if (!OutgoingCache.ContainsKey(result)) { OutgoingCache[result] = component; } break; } var context = new ContainerContext { Component = component, Operation = ContainerOperation.AfterActivate, Object = result, }; ProcessExtensions(context); return(result); } }