Example #1
0
        /// <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
                });
            }
        }
Example #2
0
        /// <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);
            }
        }
Example #3
0
 /// <summary>
 ///     Вызыает очистку контейнера
 /// </summary>
 /// <remarks>
 ///     <invariant>Очистка очищает внутрненнее состояние и кэши контейнера, регистрации компонент это не касается, компоненты остаются в прежней конфигурации</invariant>
 /// </remarks>
 public void CleanUp()
 {
     foreach (var objreg in OutgoingCache)
     {
         DropObject(objreg.Key);
     }
     foreach (var objreg in Pool)
     {
         foreach (var o in objreg.Value)
         {
             DropObject(o);
         }
     }
     OutgoingCache.Clear();
     Pool.Clear();
 }
Example #4
0
        /// <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);
            }
        }