예제 #1
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);
            }
        }
예제 #2
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);
            }
        }