AbstractObjectFactory.cs :  » Inversion-of-Control-Dependency-Injection » Spring.net » Spring » Objects » Factory » Support » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Inversion of Control Dependency Injection » Spring.net 
Spring.net » Spring » Objects » Factory » Support » AbstractObjectFactory.cs
#region License

/*
 * Copyright  2002-2005 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#endregion

#region Imports

using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.Serialization;
using Common.Logging;

using Spring.Collections;
using Spring.Core;
using Spring.Core.TypeConversion;
using Spring.Objects.Factory.Config;
using Spring.Threading;
using Spring.Util;

#endregion

namespace Spring.Objects.Factory.Support{
    /// <summary>
    /// Abstract superclass for <see cref="Spring.Objects.Factory.IObjectFactory"/>
    /// implementations.
    /// </summary>
    /// <remarks>
    /// <p>
    /// This class provides singleton / prototype determination, singleton caching,
    /// object definition aliasing, <see cref="Spring.Objects.Factory.IFactoryObject"/>
    /// handling, and object definition merging for child object definitions.
    /// </p>
    /// </remarks>
    /// <author>Rod Johnson</author>
    /// <author>Juergen Hoeller</author>
    /// <author>Rick Evans (.NET)</author>
    [Serializable]
    public abstract class AbstractObjectFactory : IConfigurableObjectFactory
    {
        [Serializable]
        private class LogicalThreadContextSetVariable : IDisposable
        {
            private readonly string name = Guid.NewGuid().ToString();

            public ISet Value
            {
                get
                {
                    ISet set = LogicalThreadContext.GetData(this.name) as ISet;
                    if (set == null)
                    {
                        set = CreateSet();
                        LogicalThreadContext.SetData(this.name, set);
                    }
                    return set;
                }
            }

            #region Implementation of IDisposable

            public void Dispose()
            {
                LogicalThreadContext.FreeNamedDataSlot(this.name);
            }

            #endregion

            private ISet CreateSet()
            {
                return new HashedSet();
            }
        }

        /// <summary>
        /// Makes a distinction between sort order and object identity. 
        /// This is important when used with <see cref="ISet"/>, since most
        /// implementations assume Order == Identity
        /// </summary>
        [Serializable]
        private class ObjectOrderComparator : OrderComparator
        {
            /// <summary>
            /// Handle the case when both objects have equal sort order priority. By default returns 0, 
            /// but may be overriden for handling special cases.
            /// </summary>
            /// <param name="o1">The first object to compare.</param>
            /// <param name="o2">The second object to compare.</param>
            /// <returns>
            /// -1 if first object is less then second, 1 if it is greater, or 0 if they are equal.
            /// </returns>
            protected override int CompareEqualOrder(object o1, object o2)
            {
                if (ReferenceEquals(o1, o2))
                    return 0;
                if (o1 == null)
                    return 1;
                if (o2 == null)
                    return -1;
                return o1.GetHashCode().CompareTo(o2.GetHashCode());
            }
        }

        /// <summary>
        /// Marker object to be temporarily registered in the singleton cache,
        /// while instantiating an object (in order to be able to detect circular references).
        /// </summary>
        private static readonly object CURRENTLY_IN_CREATION = new Object();

        /// <summary>
        /// Used as value in hashtable that keeps track of singleton names currently in the
        /// process of being created.  Would not be necessary if we created a case insensitive implementation of
        /// ISet.
        /// </summary>
        private static readonly object EMPTYOBJECT = new object();

        /// <summary>
        /// The <see cref="Common.Logging.ILog"/> instance for this class.
        /// </summary>
        private readonly ILog log;

        /// <summary>
        /// Cache of singleton objects created by <see cref="IFactoryObject"/>s: FactoryObject name -> product
        /// </summary>
        private readonly Hashtable factoryObjectProductCache = new Hashtable();

        #region Constructor (s) / Destructor

        /// <summary>
        /// Creates a new instance of the
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectFactory"/> class.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This constructor implicitly creates an
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectFactory"/>
        /// that treats the names of objects in this factory in a case-sensitive fashion.
        /// </p>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes no public constructors.
        /// </p>
        /// </remarks>
        protected AbstractObjectFactory()
            : this(true)
        { }

        /// <summary>
        /// Creates a new instance of the
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectFactory"/> class.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes no public constructors.
        /// </p>
        /// </remarks>
        /// <param name="caseSensitive">
        /// <see lang="true"/> if the names of objects in this factory are to be treated in a
        /// case-sensitive fashion.
        /// </param>
        protected AbstractObjectFactory(bool caseSensitive)
        {
            this.log = LogManager.GetLogger(this.GetType());
            this.caseSensitive = caseSensitive;
#if NET_1_0 || NET_1_1
            if (caseSensitive)
            {
                this.aliasMap = new Hashtable();
                this.singletonCache = new Hashtable();
                this.singletonsInCreation = new Hashtable();
            }
            else
            {
                this.aliasMap = new CaseInsensitiveHashtable();
                this.singletonCache = new CaseInsensitiveHashtable();
                this.singletonsInCreation = new CaseInsensitiveHashtable();
            }
#else
            IEqualityComparer comparer = (caseSensitive) ? StringComparer.Ordinal : StringComparer.OrdinalIgnoreCase;
            this.aliasMap = new OrderedDictionary(comparer);
            this.singletonCache = new OrderedDictionary(comparer);
            this.singletonsInCreation = new OrderedDictionary(comparer);
#endif
            this.prototypesInCreation = new LogicalThreadContextSetVariable();
        }

        /// <summary>
        /// Creates a new instance of the
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectFactory"/> class.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes no public constructors.
        /// </p>
        /// </remarks>
        /// <param name="caseSensitive">
        /// <see lang="true"/> if the names of objects in this factory are to be treated in a
        /// case-sensitive fashion.
        /// </param>
        /// <param name="parentFactory">
        /// Any parent object factory; may be <see lang="null"/>.
        /// </param>
        protected AbstractObjectFactory(bool caseSensitive, IObjectFactory parentFactory)
            : this(caseSensitive)
        {
            ParentObjectFactory = parentFactory;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Returns, whether this factory treats object names case sensitive or not.
        /// </summary>
        public bool IsCaseSensitive
        {
            get { return caseSensitive; }
        }

        /// <summary>
        /// Gets the <see cref="ISet"/> of
        /// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>s
        /// that will be applied to objects created by this factory.
        /// </summary>
        public ISet ObjectPostProcessors
        {
            get { return objectPostProcessors; }
        }

        /// <summary>
        /// Gets the set of classes that will be ignored for autowiring.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The elements of this <see cref="Spring.Collections.ISet"/> are
        /// <see cref="System.Type"/>s.
        /// </p>
        /// </remarks>
        public ISet IgnoredDependencyTypes
        {
            get { return ignoreDependencyTypes; }
        }

        /// <summary>
        /// Returns, whether this object factory instance contains <see cref="IInstantiationAwareObjectPostProcessor"/> objects.
        /// </summary>
        protected bool HasInstantiationAwareBeanPostProcessors
        {
            get { return hasInstantiationAwareBeanPostProcessors; }
        }

        /// <summary>
        /// Returns, whether this object factory instance contains <see cref="IDestructionAwareObjectPostProcessor"/> objects.
        /// </summary>
        protected bool HasDestructionAwareBeanPostProcessors
        {
            get { return hasDestructionAwareBeanPostProcessors; }
        }

        #endregion

        #region Methods


        /// <summary>
        /// Return an instance (possibly shared or independent) of the given object name.
        /// </summary>
        /// <param name="name">The name of the object to return.</param>
        /// <param name="requiredType">
        /// The <see cref="System.Type"/> the object may match. Can be an interface or
        /// superclass of the actual class. For example, if the value is the
        /// <see cref="System.Object"/> class, this method will succeed whatever the
        /// class of the returned instance.
        /// </param>
        /// <param name="arguments">
        /// The arguments to use if creating a prototype using explicit arguments to
        /// a <see lang="static"/> factory method. If there is no factory method and the
        /// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
        /// match the argument values by type and call the object's constructor.
        /// </param>
        /// <returns>The instance of the object.</returns>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there's no such object definition.
        /// </exception>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the object could not be created.
        /// </exception>
        /// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
        /// If the object is not of the required type.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="name"/> is <see langword="null"/>.
        /// </exception>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type)"/>
        public object GetObject(string name, Type requiredType, object[] arguments)
        {
            return GetObjectInternal(name, requiredType, arguments, false);
        }

        /// <summary>
        /// Apply the property values of the object definition with the supplied
        /// <paramref name="name"/> to the supplied <paramref name="instance"/>.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The object definition can either define a fully self-contained object,
        /// reusing it's property values, or just property values meant to be used
        /// for existing object instances.
        /// </p>
        /// </remarks>
        /// <param name="instance">
        /// The existing object that the property values for the named object will
        /// be applied to.
        /// </param>
        /// <param name="name">
        /// The name of the object definition associated with the property values that are
        /// to be applied.
        /// </param>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// In case of errors.
        /// </exception>
        public virtual void ApplyObjectPropertyValues(object instance, string name)
        {
            // explicit no-op...
        }

        /// <summary>
        /// Apply the property values of the object definition with the supplied
        /// <paramref name="name"/> to the supplied <paramref name="instance"/>.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The object definition can either define a fully self-contained object,
        /// reusing it's property values, or just property values meant to be used
        /// for existing object instances.
        /// </p>
        /// </remarks>
        /// <param name="instance">
        /// The existing object that the property values for the named object will
        /// be applied to.
        /// </param>
        /// <param name="name">
        /// The name of the object definition associated with the property values that are
        /// to be applied.
        /// </param>
        /// <param name="definition">
        /// An object definition that should be used to apply property values.
        /// </param>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// In case of errors.
        /// </exception>
        public virtual void ApplyObjectPropertyValues(object instance, string name, IObjectDefinition definition)
        {
            // explicit no-op...
        }

        //        /// <summary>
        //        /// Create an object instance for the given object definition.
        //        /// </summary>
        //        /// <remarks>
        //        /// <p>
        //        /// The object definition will already have been merged with the parent
        //        /// definition in case of a child definition.
        //        /// </p>
        //        /// <p>
        //        /// All the other methods in this class invoke this method, although objects
        //        /// may be cached after being instantiated by this method. All object
        //        /// instantiation within this class is performed by this method.
        //        /// </p>
        //        /// </remarks>
        //        /// <param name="name">The name of the object.</param>
        //        /// <param name="definition">
        //        /// The object definition for the object that is to be instantiated.
        //        /// </param>
        //        /// <param name="arguments">
        //        /// The arguments to use if creating a prototype using explicit arguments to
        //        /// a <see lang="static"/>  factory method. If there is no factory method and the
        //        /// supplied <paramref name="arguments"/> array is not <see lang="null"/>,
        //        /// then match the argument values by type and call the object's constructor.
        //        /// </param>
        //        /// <returns>
        //        /// A new instance of the object.
        //        /// </returns>
        //        /// <exception cref="Spring.Objects.ObjectsException">
        //        /// In case of errors.
        //        /// </exception>
        //        protected internal abstract object CreateObject(string name, RootObjectDefinition definition, object[] arguments);


        /// <summary>
        /// Create an object instance for the given object definition.
        /// </summary>
        /// <param name="name">The name of the object.</param>
        /// <param name="definition">
        /// The object definition for the object that is to be instantiated.
        /// </param>
        /// <param name="arguments">
        /// The arguments to use if creating a prototype using explicit arguments to
        /// a static factory method. It is invalid to use a non-<see langword="null"/> arguments value
        /// in any other case.
        /// </param>
        /// <param name="allowEagerCaching">
        /// Whether eager caching of singletons is allowed... typically true for
        /// singlton objects, but never true for inner object definitions.
        /// </param>
        /// <param name="suppressConfigure">
        /// Create instance only - suppress injecting dependencies yet.
        /// </param>
        /// <returns>
        /// A new instance of the object.
        /// </returns>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// In case of errors.
        /// </exception>
        /// <remarks>
        /// <p>
        /// The object definition will already have been merged with the parent
        /// definition in case of a child definition.
        /// </p>
        /// <p>
        /// All the other methods in this class invoke this method, although objects
        /// may be cached after being instantiated by this method. All object
        /// instantiation within this class is performed by this method.
        /// </p>
        /// </remarks>
        protected internal abstract object InstantiateObject(string name, RootObjectDefinition definition, object[] arguments,
                                                        bool allowEagerCaching, bool suppressConfigure);

        /// <summary>
        /// Destroy the target object.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Must destroy objects that depend on the given object before the object itself,
        /// nor throw an exception.
        /// </p>
        /// </remarks>
        /// <param name="name">
        /// The name of the object.
        /// </param>
        /// <param name="target">
        /// The target object instance to destroyed.
        /// </param>
        protected abstract void DestroyObject(string name, object target);

        /// <summary>
        /// Does this object factory contain an object definition with the
        /// supplied <paramref name="name"/>?
        /// </summary>
        /// <remarks>
        /// <p>
        /// Does not consider any hierarchy this factory may participate in.
        /// Invoked by
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectFactory.ContainsObject"/>
        /// when no cached singleton instance is found.
        /// </p>
        /// </remarks>
        /// <param name="name">
        /// The name of the object to look for.
        /// </param>
        /// <returns>
        /// <see lang="true"/> if this object factory contains an object
        /// definition with the supplied <paramref name="name"/>.
        /// </returns>
        public abstract bool ContainsObjectDefinition(string name);

        /// <summary>
        /// Adds the supplied <paramref name="singleton"/> (object) to this factory's
        /// singleton cache.
        /// </summary>
        /// <remarks>
        /// <p>
        /// To be called for eager registration of singletons, e.g. to be able to
        /// resolve circular references.
        /// </p>
        /// <note>
        /// If a singleton has already been registered under the same name as
        /// the supplied <paramref name="name"/>, then the old singleton will
        /// be replaced.
        /// </note>
        /// </remarks>
        /// <param name="name">The name of the object.</param>
        /// <param name="singleton">The singleton object.</param>
        /// <exception cref="System.ArgumentNullException">
        /// If the <paramref name="name"/> argument is <see langword="null"/>
        /// or consists wholly of whitespace characters; or if the
        /// <paramref name="singleton"/> is <see langword="null"/>.
        /// </exception>
        protected virtual void AddSingleton(string name, object singleton)
        {
            AssertUtils.ArgumentHasText(name, "The object name must not be empty.");
            AssertUtils.ArgumentNotNull(singleton, "singleton");
            lock (singletonCache)
            {
                singletonCache[name] = singleton;
                registeredSingletons.Add(name);
            }
        }

        /// <summary>
        /// Return the object name, stripping out the factory dereference prefix if
        /// necessary, and resolving aliases to canonical names.
        /// </summary>
        /// <param name="name">
        /// The transformed name of the object.
        /// </param>
        protected string TransformedObjectName(string name)
        {
            string objectName = ObjectFactoryUtils.TransformedObjectName(name);
            // handle aliasing...
            lock (aliasMap)
            {
                string canonicalName = (string)aliasMap[objectName];
                return canonicalName != null ? canonicalName : objectName;
            }
        }

        /// <summary>
        /// Ensures, that the given name is prefixed with <see cref="ObjectFactoryUtils.FactoryObjectPrefix"/> 
        /// if it incidentially already starts with this prefix. This avoids troubles when dereferencing 
        /// the object name during <see cref="ObjectFactoryUtils.TransformedObjectName"/>
        /// </summary>
        protected string OriginalObjectName(string name)
        {
            string objectName = TransformedObjectName(name);
            if (name.StartsWith(ObjectFactoryUtils.FactoryObjectPrefix))
            {
                objectName = ObjectFactoryUtils.FactoryObjectPrefix + objectName;
            }
            return objectName;
        }

        /// <summary>
        /// Determines whether the specified name is defined as an alias as opposed
        /// to the name of an actual object definition.
        /// </summary>
        /// <param name="name">The object name to check.</param>
        /// <returns>
        ///   <c>true</c> if the specified name is alias; otherwise, <c>false</c>.
        /// </returns>
        protected bool IsAlias(string name)
        {
            lock (aliasMap)
            {
                return aliasMap.Contains(name);
            }
        }

        /// <summary>
        /// Return a <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>,
        /// even by traversing parent if the parameter is a child definition.
        /// </summary>
        /// <param name="name">
        /// The name of the object.
        /// </param>
        /// <param name="includingAncestors">
        /// Are ancestors to be included in the merge?
        /// </param>
        /// <remarks>
        /// <p>
        /// Will ask the parent object factory if not found in this instance.
        /// </p>
        /// </remarks>
        /// <returns>
        /// A merged <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>
        /// with overridden properties.
        /// </returns>
        public virtual RootObjectDefinition GetMergedObjectDefinition(string name, bool includingAncestors)
        {
            return GetMergedObjectDefinition(name, GetObjectDefinition(name, includingAncestors));
        }

        /// <summary>
        /// Return a <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>,
        /// even by traversing parent if the parameter is a child definition.
        /// </summary>
        /// <returns>
        /// A merged <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>
        /// with overridden properties.
        /// </returns>
        protected internal virtual RootObjectDefinition GetMergedObjectDefinition(string name, IObjectDefinition od)
        {
            if (od == null)
            {
                return null;
            }

            RootObjectDefinition mod;

            if (od.ParentName == null)
            {
                mod = CreateRootObjectDefinition(od);
            }
            else
            {
                //                IObjectDefinition childDefinition = definition;
                IObjectDefinition pod = null;
                if (!name.Equals(od.ParentName))
                {
                    pod = GetMergedObjectDefinition(TransformedObjectName(od.ParentName), true);
                }
                else
                {
                    if (ParentObjectFactory is AbstractObjectFactory)
                    {
                        pod = ((AbstractObjectFactory)ParentObjectFactory).GetMergedObjectDefinition(od.ParentName, true);
                    }
                }

                if (pod == null)
                {
                    throw new NoSuchObjectDefinitionException(od.ParentName,
                                                                string.Format(
                                                                        "Parent name '{0}' is equal to object name '{1}' - "
                                                                        +
                                                                        "cannot be resolved without an AbstractObjectFactory parent.",
                                                                        od.ParentName, name));
                }

                mod = CreateRootObjectDefinition(pod);
                mod.OverrideFrom(od);
            }
            return mod;
        }

        /// <summary>
        /// Creates the root object definition.
        /// </summary>
        /// <param name="templateDefinition">The template definition to base root definition on.</param>
        /// <returns>Root object definition.</returns>
        protected virtual RootObjectDefinition CreateRootObjectDefinition(IObjectDefinition templateDefinition)
        {
            return new RootObjectDefinition(templateDefinition);
        }

        /// <summary>
        /// Register a new object definition with this registry.
        /// </summary>
        /// <param name="name">
        /// The name of the object instance to register.
        /// </param>
        /// <param name="objectDefinition">
        /// The definition of the object instance to register.
        /// </param>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the object definition is invalid.
        /// </exception>
        /// <seealso cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry.RegisterObjectDefinition(string, IObjectDefinition)"/>
        public abstract void RegisterObjectDefinition(string name, IObjectDefinition objectDefinition);

        /// <summary>
        /// Return the registered
        /// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/> for the
        /// given object, allowing access to its property values and constructor
        /// argument values.
        /// </summary>
        /// <param name="name">The name of the object.</param>
        /// <returns>
        /// The registered
        /// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/>.
        /// </returns>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there is no object with the given name.
        /// </exception>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// In the case of errors.
        /// </exception>
        public abstract IObjectDefinition GetObjectDefinition(string name);

        /// <summary>
        /// Return the registered
        /// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/> for the
        /// given object, allowing access to its property values and constructor
        /// argument values.
        /// </summary>
        /// <param name="name">The name of the object.</param>
        /// <param name="includeAncestors">Whether to search parent object factories.</param>
        /// <returns>
        /// The registered
        /// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/>.
        /// </returns>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there is no object with the given name.
        /// </exception>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// In the case of errors.
        /// </exception>
        public abstract IObjectDefinition GetObjectDefinition(string name, bool includeAncestors);

        /// <summary>
        /// Gets the type for the given FactoryObject.
        /// </summary>
        /// <param name="factoryObject">The factory object instance to check.</param>
        /// <returns>the FactoryObject's object type</returns>
        protected virtual Type GetTypeForFactoryObject(IFactoryObject factoryObject)
        {
            try
            {
                return factoryObject.ObjectType;
            }
            catch (Exception ex)
            {
                log.Warn("FactoryObject threw exception from ObjectType, despite the contract saying " +
                    "that it should return null if the type of its object cannot be determined yet", ex);
                return null;
            }
        }

        /// <summary>
        /// Gets the object type for the given FactoryObject definition, as far as possible.
        /// Only called if there is no singleton instance registered for the target object already.
        /// </summary>
        /// <remarks>
        /// The default implementation creates the FactoryObject via <code>GetObject</code>
        /// to call its <code>ObjectType</code> property. Subclasses are encouraged to optimize
        /// this, typically by just instantiating the FactoryObject but not populating it yet,
        /// trying whether its <code>ObjectType</code> property already returns a type.
        /// If no type found, a full FactoryObject creation as performed by this implementation
        /// should be used as fallback.
        /// </remarks>
        /// <param name="objectName">Name of the object.</param>
        /// <param name="mod">The merged object definition for the object.</param>
        /// <returns>The type for the object if determinable, or <code>null</code> otherwise</returns>
        protected virtual Type GetTypeForFactoryObject(string objectName, RootObjectDefinition mod)
        {
            if (!mod.IsSingleton)
            {
                return null;
            }
            try
            {
                IFactoryObject factoryObject = GetFactoryObject(objectName);
                return GetTypeForFactoryObject(factoryObject);
            }
            catch (ObjectCreationException ex)
            {
                // Can only happen when getting a FactoryObject.
                log.Warn("Ignoring object creation exception on FactoryObject type check", ex);
                return null;
            }
        }

        /// <summary>
        /// Predict the eventual object type (of the processed object instance) for the
        /// specified object.
        /// </summary>
        /// <remarks>
        /// Does not need to handle FactoryObjects specifically, since it is only
        /// supposed to operate on the raw object type.
        /// This implementation is simplistic in that it is not able to
        /// handle factory methods and InstantiationAwareBeanPostProcessors.
        /// It only predicts the object type correctly for a standard object.
        /// To be overridden in subclasses, applying more sophisticated type detection.
        /// </remarks>
        /// <param name="objectName">Name of the object.</param>
        /// <param name="mod">The merged object definition to determine the type for. May be <c>null</c></param>
        /// <returns>The type of the object, or <code>null</code> if not predictable</returns>
        protected virtual Type PredictObjectType(string objectName, RootObjectDefinition mod)
        {
            if (mod == null || StringUtils.HasText(mod.FactoryObjectName))
            {
                return null;
            }
            return ResolveObjectType(mod, objectName);
        }

        /// <summary>
        /// Get the object for the given object instance, either the object
        /// instance itself or its created object in case of an
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/>.
        /// </summary>
        /// <param name="name">
        /// The name that may include the factory dereference prefix.
        /// </param>
        /// <param name="instance">The object instance.</param>
        /// <returns>
        /// The singleton instance of the object.
        /// </returns>
        [Obsolete("")]
        protected internal virtual object GetObjectForInstance(string name, object instance)
        {
            return GetObjectForInstance(instance, name, TransformedObjectName(name), null);
        }

        /// <summary>
        /// Get the object for the given object instance, either the object
        /// instance itself or its created object in case of an
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/>.
        /// </summary>
        /// <param name="instance">The object instance.</param>
        /// <param name="name">
        /// The name that may include the factory dereference prefix (=the requested name).
        /// </param>
        /// <param name="canonicalName">
        /// The canonical object name
        /// </param>
        /// <param name="rod">the merged object definition</param>
        /// <returns>
        /// The singleton instance of the object.
        /// </returns>
        protected internal virtual object GetObjectForInstance(object instance, string name, string canonicalName, RootObjectDefinition rod)
        {
            // don't let calling code try to dereference the
            // object factory if the object isn't a factory
            if (IsFactoryDereference(name) && !(ObjectUtils.IsAssignable(typeof(IFactoryObject), instance)))
            {
                throw new ObjectIsNotAFactoryException(canonicalName, instance);
            }

            // now we have the object instance, which may be a normal object
            // or an IFactoryObject. If it's an IFactoryObject and the caller wants
            // a reference to the factory there's nothing more to do


            // it's a normal object ?
            if (!ObjectUtils.IsAssignable(typeof(IFactoryObject), instance))
            {
                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("Calling code asked for normal instance for name '{0}'.", canonicalName));
                }

                #endregion

                return instance;
            }

            // the user wants the factory itself ?
            if (!ObjectUtils.IsAssignable(typeof(IFactoryObject), instance) || IsFactoryDereference(name))
            {
                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(
                        string.Format("Calling code asked for IFactoryObject instance for name '{0}'.",
                                      TransformedObjectName(name)));
                }

                #endregion

                return instance;
            }

            #region Instrumentation

            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format("Object with name '{0}' is a factory object.", canonicalName));
            }

            #endregion

            object resultInstance = null;

            if (rod == null)
            {
                resultInstance = factoryObjectProductCache[canonicalName];
            }

            if (resultInstance == null)
            {
                #region Instrumentation
                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("Dereferencing Object with name '{0}'", canonicalName));
                }
                #endregion

                // return object instance from factory...
                IFactoryObject factory = (IFactoryObject)instance;

                if (rod == null && ContainsObjectDefinition(canonicalName))
                {
                    rod = GetMergedObjectDefinition(canonicalName, true);
                }

                if (factory.IsSingleton && ContainsSingleton(canonicalName))
                {
                    lock (factoryObjectProductCache.SyncRoot)
                    {
                        resultInstance = factoryObjectProductCache[canonicalName];
                        if (resultInstance == null)
                        {
                            resultInstance = GetObjectFromFactoryObject(factory, canonicalName, rod);
                            if (resultInstance != null)
                            {
                                factoryObjectProductCache[canonicalName] = resultInstance;
                            }
                        }
                    }
                }
                else
                {
                    resultInstance = GetObjectFromFactoryObject(factory, canonicalName, rod);
                }

                if (resultInstance == null)
                {
                    throw new FactoryObjectNotInitializedException(canonicalName,
                                                                   "Factory object returned null object - "
                                                                   + "possible cause: not fully initialized due to "
                                                                   + "circular object reference.");
                }
            }
            else
            {
                #region Instrumentation
                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("Returning factory product from cache for Object with name '{0}'", canonicalName));
                }
                #endregion
            }
            return resultInstance;
        }

        /// <summary>
        /// Obtain an object to expose from the given IFactoryObject.
        /// </summary>
        /// <param name="factory">The IFactoryObject instance.</param>
        /// <param name="objectName">Name of the object.</param>
        /// <param name="rod">The merged object definition.</param>
        /// <returns>The object obtained from the IFactoryObject</returns>
        /// <exception cref="ObjectCreationException">If IFactoryObject object creation failed.</exception>
        private object GetObjectFromFactoryObject(IFactoryObject factory, string objectName, RootObjectDefinition rod)
        {
            object instance;

            try
            {
                instance = factory.GetObject();
            }
            catch (FactoryObjectNotInitializedException ex)
            {
                throw new ObjectCurrentlyInCreationException(
                    rod.ResourceDescription, objectName, ex);
            }
            catch (Exception ex)
            {
                throw new ObjectCreationException(rod.ResourceDescription, objectName,
                    "FactoryObject threw exception on object creation.", ex);
            }

            // Do not accept a null value for a FactoryBean that's not fully
            // initialized yet: Many FactoryBeans just return null then.
            if (instance == null && IsSingletonCurrentlyInCreation(objectName))
            {
                throw new ObjectCurrentlyInCreationException(rod.ResourceDescription, objectName,
                    "FactoryObject which is currently in creation returned null from GetObject.");
            }

            if (factory is IConfigurableFactoryObject)
            {
                IConfigurableFactoryObject configurableFactory = (IConfigurableFactoryObject)factory;

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("Factory object with name '{0}' is configurable.", TransformedObjectName(objectName)));
                }

                #endregion

                if (configurableFactory.ProductTemplate != null)
                {
                    ApplyObjectPropertyValues(instance, objectName, configurableFactory.ProductTemplate);
                }
            }

            if (instance != null)
            {
                try
                {
                    instance = PostProcessObjectFromFactoryObject(instance, objectName);
                }
                catch (Exception ex)
                {
                    throw new ObjectCreationException(rod.ResourceDescription, objectName,
                                "Post-processing of the FactoryObject's object failed.", ex);
                }
            }

            return instance;
        }

        /// <summary>
        /// Post-process the given object that has been obtained from the FactoryObject.
        /// The resulting object will be exposed for object references.
        /// </summary>
        /// <remarks>The default implementation simply returns the given object
        /// as-is.  Subclasses may override this, for example, to apply
        /// post-processors.</remarks>
        /// <param name="instance">The instance obtained from the IFactoryObject.</param>
        /// <param name="objectName">Name of the object.</param>
        /// <returns>The object instance to expose</returns>
        /// <exception cref="ObjectsException">if any post-processing failed.</exception>
        protected virtual object PostProcessObjectFromFactoryObject(object instance, string objectName)
        {
            return instance;
        }

        /// <summary>
        /// Convenience method to pull an <see cref="Spring.Objects.Factory.IFactoryObject"/>
        /// from this factory.
        /// </summary>
        /// <param name="objectName">
        /// The name of the factory object to be retrieved. If this name is not a valid
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/> name, it will be converted
        /// into one.
        /// </param>
        /// <returns>
        /// The <see cref="Spring.Objects.Factory.IFactoryObject"/> associated with the
        /// supplied <paramref name="objectName"/>.
        /// </returns>
        protected IFactoryObject GetFactoryObject(string objectName)
        {
            if (!ObjectFactoryUtils.IsFactoryDereference(objectName))
            {
                objectName = ObjectFactoryUtils.BuildFactoryObjectName(objectName);
            }
            return (IFactoryObject)GetObject(objectName);
        }

        /// <summary>
        /// Is the supplied <paramref name="name"/> a factory object dereference?
        /// </summary>
        protected bool IsFactoryDereference(string name)
        {
            return ObjectFactoryUtils.IsFactoryDereference(name);
        }

        /// <summary>
        /// Determines whether the type of the given object definition matches the
        /// specified target type.
        /// </summary>
        /// <remarks>Allows for lazy load of the actual object type, provided that the
        /// type match can be determined otherwise.
        /// <para>The default implementation simply delegates to the standard
        /// <code>ResolveObjectType</code> method.  Subclasses may override this to use
        /// a differnt strategy.</para>
        /// </remarks>
        /// <param name="objectName">Name of the object (for error handling purposes).</param>
        /// <param name="rod">The merged object definition to determine the type for.</param>
        /// <param name="targetType">Type to match against (never null).</param>
        /// <returns>
        ///   <c>true</c> if object definition matches tye specified target type; otherwise, <c>false</c>.
        /// </returns>
        /// <exception cref="CannotLoadObjectTypeException">if we failed to load the type.</exception>"
        protected bool IsObjectTypeMatch(string objectName, RootObjectDefinition rod, Type targetType)
        {
            Type objectType = ResolveObjectType(rod, objectName);
            return (objectType != null && targetType.IsAssignableFrom(objectType));
        }

        /// <summary>
        /// Resolves the type of the object for the specified object definition resolving
        /// an object type name to a Type (if necessary) and storing the resolved Type
        /// in the object definition for further use.
        /// </summary>
        /// <param name="rod">The merged object definition to dertermine the type for.</param>
        /// <param name="objectName">Name of the object (for error handling purposes).</param>
        /// <returns></returns>
        protected Type ResolveObjectType(RootObjectDefinition rod, string objectName)
        {
            try
            {
                if (rod.HasObjectType)
                {
                    return rod.ObjectType;
                }
                return rod.ResolveObjectType();
            }
            catch (TypeLoadException e)
            {
                throw new CannotLoadObjectTypeException(rod.ResourceDescription, objectName, rod.ObjectTypeName, e);
            }
        }

        /// <summary>
        /// Is the object (definition) with the supplied <paramref name="name"/> an
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/>?
        /// </summary>
        /// <param name="name">The name of the object to be checked.</param>
        /// <returns>
        /// <see lang="true"/> the object (definition) with the supplied
        /// <paramref name="name"/> an <see cref="Spring.Objects.Factory.IFactoryObject"/>?
        /// </returns>
        protected bool IsFactoryObject(string name)
        {
            string objectName = TransformedObjectName(name);
            object objectInstance = GetSingleton(objectName);

            if (objectInstance != null)
            {
                return (objectInstance is IFactoryObject);
            }
            else
            {
                RootObjectDefinition definition = GetMergedObjectDefinition(objectName, false);
                if (definition != null)
                {
                    return (definition.HasObjectType && typeof(IFactoryObject).IsAssignableFrom(definition.ObjectType));
                }
                else
                {
                    if (parentObjectFactory != null)
                    {
                        return ((AbstractObjectFactory)parentObjectFactory).IsFactoryObject(name);
                    }
                    else
                    {
                        throw new NoSuchObjectDefinitionException(objectName,
                                                                  "Cannot find definition for object [" + objectName
                                                                  + "]");
                    }
                }
            }
        }

        /// <summary>
        /// Remove the object identified by the supplied <paramref name="name"/>
        /// from this factory's singleton cache.
        /// </summary>
        /// <param name="name">
        /// The name of the object that is to be removed from the singleton
        /// cache.
        /// </param>
        /// <exception cref="System.ArgumentNullException">
        /// If the <paramref name="name"/> argument is <see langword="null"/> or
        /// consists wholly of whitespace characters.
        /// </exception>
        protected void RemoveSingleton(string name)
        {
            AssertUtils.ArgumentHasText(name, "name");
            lock (singletonCache)
            {
                this.singletonCache.Remove(name);
            }
        }

        /// <summary>
        /// Return the names of objects in the singleton cache that match the given
        /// object type (including subclasses).
        /// </summary>
        /// <param name="type">
        /// The class or interface to match, or <see langword="null"/> for all object names.
        /// </param>
        /// <remarks>
        /// <p>
        /// Will <i>not</i> consider <see cref="Spring.Objects.Factory.IFactoryObject"/>s
        /// as the type of their created objects is not known before instantiation.
        /// </p>
        /// <p>
        /// Does not consider any hierarchy this factory may participate in.
        /// </p>
        /// </remarks>
        /// <returns>
        /// The names of objects in the singleton cache that match the given
        /// object type (including subclasses), or an empty array if none.
        /// </returns>
        public virtual string[] GetSingletonNames(Type type)
        {
            lock (singletonCache)
            {
                ArrayList matches = new ArrayList();
                foreach (string name in singletonCache.Keys)
                {
                    object singletonObject = singletonCache[name];
                    if (singletonObject != null && type.IsAssignableFrom(singletonObject.GetType())
                        && !matches.Contains(name))
                    {
                        matches.Add(name);
                    }
                }
                return (string[])matches.ToArray(typeof(string));
            }
        }

        /// <summary>
        /// Determines whether the object with the given name matches the specified type.
        /// </summary>
        /// <remarks>More specifically, check whether a GetObject call for the given name
        /// would return an object that is assignable to the specified target type.
        /// Translates aliases back to the corresponding canonical bean name.
        /// Will ask the parent factory if the bean cannot be found in this factory instance.
        /// </remarks>
        /// <param name="name">The name of the object to query.</param>
        /// <param name="targetType">Type of the target to match against.</param>
        /// <returns>
        ///   <c>true</c> if the object type matches; otherwise, <c>false</c>
        /// if it doesn't match or cannot be determined yet.
        /// </returns>
        /// <exception cref="NoSuchObjectDefinitionException">Ff there is no object with the given name
        /// </exception>
        public bool IsTypeMatch(string name, Type targetType)
        {
            string objectName = TransformedObjectName(name);
            Type typeToMatch = (targetType != null ? targetType : typeof(object));

            //Check manually registered singletons.
            object objectInstance = GetSingleton(objectName);
            if (objectInstance != null)
            {
                if (objectInstance is IFactoryObject)
                {
                    if (!IsFactoryDereference(name))
                    {
                        Type type = GetTypeForFactoryObject((IFactoryObject)objectInstance);
                        return (type != null && typeToMatch.IsAssignableFrom(type));
                    }
                    else
                    {
                        return typeToMatch.IsAssignableFrom(objectInstance.GetType());
                    }
                }
                else
                {
                    return !IsFactoryDereference(name) && typeToMatch.IsAssignableFrom(objectInstance.GetType());
                }
            }
            else
            {
                // No singleton instance found -> check object definition
                IObjectFactory parentFactory = ParentObjectFactory;
                if (parentFactory != null && !ContainsObjectDefinition(name))
                {
                    // No object definition found in this factory -> delegate to parent
                    return parentFactory.IsTypeMatch(OriginalObjectName(name), targetType);
                }

                RootObjectDefinition mod = GetMergedObjectDefinition(objectName, false);
                Type objectType = PredictObjectType(objectName, mod);

                if (objectType == null)
                {
                    return false;
                }

                // Check object class whether we're dealing with a FactoryObject
                if (typeof(IFactoryObject).IsAssignableFrom(objectType))
                {
                    if (!IsFactoryDereference(name))
                    {
                        // If it's a FactoryObject, we want to look at what it creates, not the factory class.
                        Type type = GetTypeForFactoryObject(objectName, mod);
                        return (type != null && typeToMatch.IsAssignableFrom(type));
                    }
                    else
                    {
                        return typeToMatch.IsAssignableFrom(objectType);
                    }
                }
                else
                {
                    return !IsFactoryDereference(name) && typeToMatch.IsAssignableFrom(objectType);
                }
            }
        }

        /// <summary>
        /// Determines the <see cref="System.Type"/> of the object with the
        /// supplied <paramref name="name"/>.
        /// </summary>
        /// <remarks>
        /// <p>
        /// More specifically, checks the <see cref="System.Type"/> of object that
        /// <see cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/> would return.
        /// For an <see cref="Spring.Objects.Factory.IFactoryObject"/>, returns the
        /// <see cref="System.Type"/> of object that the
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/> creates.
        /// </p>
        /// <p>
        /// Please note that (prototype) objects created via a factory method or
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/> objects are handled
        /// slightly differently, in that we <b>don't</b> want to needlessly create
        /// instances of such objects just to determine the <see cref="System.Type"/>
        /// of object that they create.
        /// </p>
        /// </remarks>
        /// <param name="name">The name of the object to query.</param>
        /// <returns>
        /// The <see cref="System.Type"/> of the object or <see langword="null"/>
        /// if not determinable.
        /// </returns>
        public virtual Type GetType(string name)
        {
            string objectName = TransformedObjectName(name);

            // check manually registered singletons...
            object objectInstance = GetSingleton(objectName);

            if (objectInstance != null)
            {
                IFactoryObject factoryObject = objectInstance as IFactoryObject;
                if (factoryObject != null & !IsFactoryDereference(objectName))
                {
                    return GetTypeForFactoryObject(factoryObject);
                }
                else
                {
                    return objectInstance.GetType();
                }
            }
            else
            {
                // No singleton instance found -> check bean definition.
                IObjectFactory parentFactory = ParentObjectFactory;
                if (parentFactory != null && !ContainsObjectDefinition(objectName))
                {
                    // No bean definition found in this factory -> delegate to parent.
                    return parentFactory.GetType(this.OriginalObjectName(name));
                }

                RootObjectDefinition mod = this.GetMergedObjectDefinition(objectName, false);
                Type objectType = PredictObjectType(objectName, mod);

                if (objectType != null && typeof(IFactoryObject).IsAssignableFrom(objectType))
                {
                    if (!IsFactoryDereference(name))
                    {
                        // If it's a FactoryBean, we want to look at what it creates, not the factory class.
                        return GetTypeForFactoryObject(objectName, mod);
                    }
                    else
                    {
                        return objectType;
                    }
                }
                else
                {
                    return (!IsFactoryDereference(name) ? objectType : null);
                }
            }
        }

        /// <summary>
        /// Determines the <see cref="System.Type"/> of the object defined
        /// by the supplied object <paramref name="definition"/>. 
        /// </summary>
        /// <remarks>
        /// <p>
        /// This, the default, implementation returns <see lang="null"/>
        /// to indicate that the type cannot be determined. Subclasses are
        /// encouraged to try to determine the actual return
        /// <see cref="System.Type"/> here, matching their strategy of resolving
        /// factory methods in the
        /// <code>Spring.Objects.Factory.Support.AbstractObjectFactory.CreateObject</code>
        /// implementation.
        /// </p>
        /// </remarks>
        /// <param name="objectName">
        /// The name associated with the supplied object <paramref name="definition"/>.
        /// </param>
        /// <param name="definition">
        /// The <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>
        /// that the <see cref="System.Type"/> is to be determined for. 
        /// </param>
        /// <returns>
        /// The <see cref="System.Type"/> of the object defined by the supplied
        /// object <paramref name="definition"/>; or <see lang="null"/> if the
        /// <see cref="System.Type"/> cannot be determined.
        /// </returns>
        protected virtual Type GetTypeForFactoryMethod(string objectName, RootObjectDefinition definition)
        {
            return null;
        }

        /// <summary>
        /// Returns the names of the objects in the singleton cache.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Does not consider any hierarchy this factory may participate in.
        /// </p>
        /// </remarks>
        /// <returns>The names of the objects in the singleton cache.</returns>
        public virtual string[] GetSingletonNames()
        {
            lock (singletonCache)
            {
                ICollection keys = singletonCache.Keys;
                return (string[])new ArrayList(keys).ToArray(typeof(string));
            }
        }

        /// <summary>
        /// Returns the number of objects in the singleton cache.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Does not consider any hierarchy this factory may participate in.
        /// </p>
        /// </remarks>
        /// <returns>The number of objects in the singleton cache.</returns>
        public virtual int GetSingletonCount()
        {
            lock (singletonCache)
            {
                return singletonCache.Count;
            }
        }

        /// <summary>
        /// Destroys the named singleton object.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Delegates to
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectFactory.DestroyObject"/>
        /// if a corresponding singleton instance is found.
        /// </p>
        /// </remarks>
        /// <param name="name">
        /// The name of the singleton object that is to be destroyed.
        /// </param>
        /// <seealso cref="Spring.Objects.Factory.Support.AbstractObjectFactory.DestroyObject"/>
        protected virtual void DestroySingleton(string name)
        {
            lock (singletonCache)
            {
                object tempObject = singletonCache[name];
                singletonCache.Remove(name);
                registeredSingletons.Remove(name);

                object singletonInstance = tempObject;
                if (singletonInstance != null)
                {
                    DestroyObject(name, singletonInstance);
                }
            }
        }

        /// <summary>
        /// Check the supplied merged object definition for any possible
        /// validation errors.
        /// </summary>
        /// <param name="mergedObjectDefinition">
        /// The object definition to be checked for validation errors.
        /// </param>
        /// <param name="objectName">
        /// The name of the object associated with the supplied object definition.
        /// </param>
        /// <param name="requiredType">
        /// The <see cref="System.Type"/> the object may match. Can be an interface or
        /// superclass of the actual class. For example, if the value is the
        /// <see cref="System.Object"/> class, this method will succeed whatever the
        /// class of the returned instance.
        /// </param>
        /// <param name="arguments">
        /// The arguments to use if creating a prototype using explicit arguments to
        /// a <see lang="static"/> factory method. If there is no factory method and the
        /// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
        /// match the argument values by type and call the object's constructor.
        /// </param>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// In the case of object validation errors.
        /// </exception>
        protected void CheckMergedObjectDefinition(RootObjectDefinition mergedObjectDefinition, String objectName,
                                                   Type requiredType, params object[] arguments)
        {
            // check if required type can match according to the object definition;
            // this is only possible at this early stage for conventional objects!
            if (mergedObjectDefinition.HasObjectType)
            {
                Type objectType = mergedObjectDefinition.ObjectType;
                if (requiredType != null && StringUtils.IsNullOrEmpty(mergedObjectDefinition.FactoryMethodName)
                    && !typeof(IFactoryObject).IsAssignableFrom(objectType)
                    && !requiredType.IsAssignableFrom(objectType))
                {
                    throw new ObjectNotOfRequiredTypeException(objectName, requiredType, objectType);
                }
            }

            // check validity of the usage of the args parameter; this can
            // only be used for prototypes constructed via a factory method...
            if (arguments != null)
            {
                if (mergedObjectDefinition.IsSingleton)
                {
                    throw new ObjectDefinitionStoreException("Cannot specify arguments in the GetObject () method when "
                                                             + "referring to a singleton object definition.");
                }

                if (mergedObjectDefinition.HasObjectType
                    && typeof(IFactoryObject).IsAssignableFrom(mergedObjectDefinition.ObjectType))
                {
                    throw new ObjectDefinitionStoreException("Cannot specify arguments in the GetObject () method when "
                                                             + "referring to a factory object definition.");
                }

                //MLP lets skip this check for now.
                /*
                else if (StringUtils.IsNullOrEmpty(mergedObjectDefinition.FactoryMethodName))
                {
                    throw new ObjectDefinitionStoreException(
                        "Can only specify arguments in the GetObject () method in " +
                            "conjunction with a factory method.");
                }
                */
            }
        }

        /// <summary>
        /// Gets the temporary object that is placed 
        /// into the singleton cache during object resolution.
        /// </summary>
        protected object TemporarySingletonPlaceHolder
        {
            get { return CURRENTLY_IN_CREATION; }
        }

        #endregion

        #region Fields

        /// <summary>
        /// Parent object factory, for object inheritance support
        /// </summary>
        private IObjectFactory parentObjectFactory;

        /// <summary>
        /// Dependency types to ignore on dependency check and autowire, as Set of
        /// Type objects: for example, string.  Default is none.
        /// </summary>
        private ISet ignoreDependencyTypes = new HybridSet();


        /// <summary>
        /// ObjectPostProcessors to apply in CreateObject
        /// </summary>
        private ISet objectPostProcessors = new SortedSet(new ObjectOrderComparator());

        /// <summary>
        /// Indicates whether any IInstantiationAwareBeanPostProcessors have been registered
        /// </summary>
        private bool hasInstantiationAwareBeanPostProcessors;

        /// <summary>
        /// Indicates whether any IDestructionAwareBeanPostProcessors have been registered 
        /// </summary>
        private bool hasDestructionAwareBeanPostProcessors;

        private bool caseSensitive;
        private IDictionary aliasMap;
        private IDictionary singletonCache;

        /// <summary>
        /// Set of registered singletons, containing the bean names in registration order 
        /// </summary>
        private ISet registeredSingletons = new HashedSet();

        private readonly IDictionary singletonsInCreation;

        private readonly LogicalThreadContextSetVariable prototypesInCreation;

        /// <summary>
        /// Set that holds all inner objects created by this factory that implement the IDisposable
        /// interface, to be destroyed on call to Dispose.
        /// </summary>
        private ISet disposableInnerObjects = new SynchronizedSet(new HybridSet());

        #endregion

        /// <summary>
        /// Set that holds all inner objects created by this factory that implement the IDisposable
        /// interface, to be destroyed on call to Dispose.
        /// </summary>
        protected internal ISet DisposableInnerObjects
        {
            get { return disposableInnerObjects; }
        }

        #region IHierarchicalObjectFactory Members

        /// <summary>
        /// The parent object factory, or <see langword="null"/> if there is none.
        /// </summary>
        /// <value>
        /// The parent object factory, or <see langword="null"/> if there is none.
        /// </value>
        public IObjectFactory ParentObjectFactory
        {
            get { return parentObjectFactory; }
            set { parentObjectFactory = value; }
        }

        /// <summary>
        /// Determines whether the local object factory contains a bean of the given name,
        /// ignoring object defined in ancestor contexts.
        /// This is an alternative to <code>ContainsObject</code>, ignoring an object
        /// of the given name from an ancestor object factory.
        /// </summary>
        /// <param name="name">The name of the object to query.</param>
        /// <returns>
        ///   <c>true</c> if objects with the specified name is defined in the local factory; otherwise, <c>false</c>.
        /// </returns>
        public bool ContainsLocalObject(string name)
        {
            string objectName = TransformedObjectName(name);
            return ((ContainsSingleton(objectName) || ContainsObjectDefinition(objectName)) &&
                    (!ObjectFactoryUtils.IsFactoryDereference(name) || IsFactoryObject(objectName)));
        }

        #endregion

        #region IObjectFactory Members

        #region New region

        /// <summary>
        /// Is this object a singleton?
        /// </summary>
        /// <see cref="Spring.Objects.Factory.IObjectFactory.IsSingleton"/> 
        public bool IsSingleton(string name)
        {
            string objectName = TransformedObjectName(name);
            object objectInstance = this.GetSingleton(objectName);
            if (objectInstance != null)
            {
                IFactoryObject factoryObject = objectInstance as IFactoryObject;
                if (factoryObject != null)
                {
                    return IsFactoryDereference(name) || factoryObject.IsSingleton;
                }
                else
                {
                    return !IsFactoryDereference(name);
                }
            }
            else
            {
                // No singleton instance found -> check object definition
                IObjectFactory pof = ParentObjectFactory;
                if (pof != null && !ContainsObjectDefinition(objectName))
                {
                    // No object definition found in this factory -> delegate to parent
                    return pof.IsSingleton(OriginalObjectName(name));
                }
                RootObjectDefinition od = GetMergedObjectDefinition(objectName, false);
                if (od == null)
                {
                    throw new NoSuchObjectDefinitionException(objectName);
                }
                // In case of IFactoryObject, return singleton status of created object if not a dereference
                if (od.IsSingleton)
                {
                    if (IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)))
                    {
                        if (IsFactoryDereference(name))
                        {
                            return true;
                        }
                        IFactoryObject factoryObject =
                            (IFactoryObject)GetObject(ObjectFactoryUtils.BuildFactoryObjectName(objectName));
                        return factoryObject.IsSingleton;
                    }
                    else
                    {
                        return !IsFactoryDereference(name);
                    }
                }
                else
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// Determines whether the specified object name is prototype.  That is, will GetObject
        /// always return independent instances?
        /// </summary>
        /// <param name="name">The name of the object to query</param>
        /// <returns>
        ///   <c>true</c> if the specified object name will always deliver independent instances; otherwise, <c>false</c>.
        /// </returns>
        /// <remarks>This method returning false does not clearly indicate a singleton object.
        /// It indicated non-independent instances, which may correspond to a scoped object as
        /// well.  use the IsSingleton property to explicitly check for a shared
        /// singleton instance.
        /// <para>Translates aliases back to the corresponding canonical object name.  Will ask the
        /// parent factory if the object can not be found in this factory instance.
        /// </para>
        /// </remarks>
        /// <exception cref="NoSuchObjectDefinitionException">if there is no object with the given name.</exception>
        public bool IsPrototype(string name)
        {
            string objectName = TransformedObjectName(name);
            IObjectFactory parentFactory = ParentObjectFactory;
            if (parentFactory != null && !this.ContainsObjectDefinition(objectName))
            {
                // No object definition found in this factory -> delegate to parent   
                return parentFactory.IsPrototype(OriginalObjectName(name));
            }

            RootObjectDefinition od = GetMergedObjectDefinition(objectName, false);

            // In case of FactoryObject, return singleton status of created object if not a dereference
            if (od.IsPrototype)
            {
                return (!IsFactoryDereference(name) || IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)));
            }
            else
            {
                // not a prototype, however factory object may still produce a prototype object
                if (IsFactoryDereference(name) && IsObjectTypeMatch(objectName, od, typeof(IFactoryObject)))
                {
                    IFactoryObject factoryObject = GetFactoryObject(objectName);
                    return (!factoryObject.IsSingleton);
                }
                else
                {
                    return false;
                }
            }
        }

        /// <summary>
        /// Does this object factory or one of its parent factories contain an object with the given name?
        /// </summary>
        /// <remarks>
        /// This method scans the object factory hierarchy starting with the current factory instance upwards. 
        /// Use <see cref="ContainsLocalObject"/> if you want to explicitely check just this object factory instance.
        /// </remarks>
        /// <see cref="Spring.Objects.Factory.IObjectFactory.ContainsObject"/>.
        public bool ContainsObject(string name)
        {
            string objectName = TransformedObjectName(name);

            if (ContainsSingleton(objectName) ||ContainsObjectDefinition(objectName))
            {
                return (!ObjectFactoryUtils.IsFactoryDereference(name) || IsFactoryObject(name));
            }

            IObjectFactory parent = this.ParentObjectFactory;
            return (parent != null) && parent.ContainsObject(OriginalObjectName(name));
        }

        /// <summary>
        /// Return the aliases for the given object name, if defined.
        /// </summary>
        /// <see cref="Spring.Objects.Factory.IObjectFactory.GetAliases"/>.
        public string[] GetAliases(string name)
        {
            string objectName = TransformedObjectName(name);
            // check if object actually exists in this object factory...
            bool isInSingletonCache = ContainsSingleton(objectName);
            if (isInSingletonCache || ContainsObjectDefinition(objectName))
            {
                // if found, gather aliases...
                ArrayList matches = new ArrayList();
                lock (aliasMap)
                {
                    foreach (DictionaryEntry aliasEntry in aliasMap)
                    {
                        if (0 == string.Compare((string)aliasEntry.Value, objectName, !this.IsCaseSensitive))
                        {
                            matches.Add(aliasEntry.Key);
                        }
                    }
                }
                return (string[])matches.ToArray(typeof(string));
            }

            // not found, so check parent...
            if (ParentObjectFactory != null)
            {
                return ParentObjectFactory.GetAliases(objectName);
            }
            throw new NoSuchObjectDefinitionException(objectName, ToString());
        }

        /// <summary>
        /// Return an instance (possibly shared or independent) of the given object name.
        /// </summary>
        /// <see cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/>.
        public object this[string name]
        {
            get { return GetObject(name); }
        }

        /// <summary>
        /// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.CreateObject(string, Type, object[])"/>
        /// <remarks>
        ///  This method will only <b>instantiate</b> the requested object. It does <b>NOT</b> inject any dependencies!
        /// </remarks>
        public object CreateObject(string name, Type requiredType, object[] arguments)
        {
            return GetObjectInternal(name, requiredType, arguments, true);
        }

        /// <summary>
        /// Return an instance (possibly shared or independent) of the given object name.
        /// </summary>
        /// <see cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/>.
        public object GetObject(string name)
        {
            return GetObjectInternal(name, null, null, false);
        }

        /// <summary>
        /// Return an instance (possibly shared or independent) of the given object name.
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type)"/>
        public object GetObject(string name, Type requiredType)
        {
            return GetObjectInternal(name, requiredType, null, false);
        }

        /// <summary>
        /// Return an instance (possibly shared or independent) of the given object name.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This method allows an object factory to be used as a replacement for the
        /// Singleton or Prototype design pattern.
        /// </p>
        /// <p>
        /// Note that callers should retain references to returned objects. There is no
        /// guarantee that this method will be implemented to be efficient. For example,
        /// it may be synchronized, or may need to run an RDBMS query.
        /// </p>
        /// <p>
        /// Will ask the parent factory if the object cannot be found in this factory
        /// instance.
        /// </p>
        /// </remarks>
        /// <param name="name">The name of the object to return.</param>
        /// <param name="arguments">
        /// The arguments to use if creating a prototype using explicit arguments to
        /// a static factory method. If there is no factory method and the
        /// arguments are not null, then match the argument values by type and
        /// call the object's constructor.
        /// </param>
        /// <returns>The instance of the object.</returns>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there's no such object definition.
        /// </exception>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the object could not be created.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="name"/> is <see langword="null"/>.
        /// </exception>
        public object GetObject(string name, object[] arguments)
        {
            return GetObjectInternal(name, null, arguments, false);

            //            string objectName = TransformedObjectName(name);
            //            object instance = null;
            //
            //            // check if object definition exists
            //            RootObjectDefinition mergedObjectDefinition = null;
            //            mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
            //            if (mergedObjectDefinition == null)
            //            {
            //                if (ParentObjectFactory != null)
            //                {
            //                    return ParentObjectFactory.GetObject(name, arguments);
            //                }
            //                throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
            //            }
            //
            //            // Override constructor values and configure as a prototype
            //            RootObjectDefinition tmpObjectDefinition = new RootObjectDefinition(mergedObjectDefinition);
            //            tmpObjectDefinition.ConstructorArgumentValues = null;
            //            tmpObjectDefinition.IsSingleton = false;
            //
            //            // create a new instance...
            //            instance = CreateObject(name, tmpObjectDefinition, arguments);
            //
            //            return GetObjectForInstance(name, instance);
        }

        /// <summary>
        /// Return an instance (possibly shared or independent) of the given object name, 
        /// optionally injecting dependencies.
        /// </summary>
        /// <param name="name">The name of the object to return.</param>
        /// <param name="requiredType">
        /// The <see cref="System.Type"/> the object may match. Can be an interface or
        /// superclass of the actual class. For example, if the value is the
        /// <see cref="System.Object"/> class, this method will succeed whatever the
        /// class of the returned instance.
        /// </param>
        /// <param name="arguments">
        /// The arguments to use if creating a prototype using explicit arguments to
        /// a <see lang="static"/> factory method. If there is no factory method and the
        /// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
        /// match the argument values by type and call the object's constructor.
        /// </param>
        /// <param name="suppressConfigure">whether to inject dependencies or not.</param>
        /// <returns>The instance of the object.</returns>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there's no such object definition.
        /// </exception>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the object could not be created.
        /// </exception>
        /// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
        /// If the object is not of the required type.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="name"/> is <see langword="null"/>.
        /// </exception>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.CreateObject(string, Type, object[])"/>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type, object[])"/>
        protected object GetObjectInternal(string name, Type requiredType, object[] arguments, bool suppressConfigure)
        {
            const int INDENT = 3;
            bool hasErrors = false;
            try
            {
                string objectName = TransformedObjectName(name);

                nestingCount++;

                #region Instrumentation
                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("{2}GetObjectInternal: obtaining instance for name {0} => canonical name {1}", name, objectName, new String(' ', nestingCount * INDENT)));
                }
                #endregion

                object instance = null;

                // those are cases, where singleton cache can be used
                if (arguments == null && !suppressConfigure)
                {
                    // eagerly check singleton cache for manually registered singletons...                       
                    object sharedInstance = GetSingleton(objectName);
                    if (sharedInstance != null)
                    {
                        #region Instrumentation
                        if (log.IsDebugEnabled)
                        {
                            if (IsSingletonCurrentlyInCreation(objectName))
                            {
                                log.Debug("Returning eagerly cached instance of singleton object '" + objectName +
                                          "' that is not fully initialized yet - a consequence of a circular reference");
                            }
                            else
                            {
                                log.Debug(string.Format("Returning cached instance of singleton object '{0}'.", objectName));
                            }
                        }
                        #endregion

                        instance = GetObjectForInstance(sharedInstance, name, objectName, null);
                        return EnsureObjectIsOfRequiredType(name, instance, requiredType);
                    }
                }

                if (IsPrototypeCurrentlyInCreation(name))
                {
                    throw new ObjectCurrentlyInCreationException(name);
                }

                // check if object definition exists
                RootObjectDefinition mergedObjectDefinition = null;
                mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
                if (mergedObjectDefinition == null)
                {
                    if (ParentObjectFactory != null)
                    {
                        return ParentObjectFactory.GetObject(name, requiredType, arguments);
                    }
                    throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
                }

                if (arguments != null
                    || suppressConfigure)
                {
                    // Clone ObjectDefinition
                    mergedObjectDefinition = CreateRootObjectDefinition(mergedObjectDefinition);
                    mergedObjectDefinition.IsSingleton = false;
                    if (arguments != null)
                    {
                        // Override constructor values and configure as a prototype if arguments are specified
                        mergedObjectDefinition.ConstructorArgumentValues = null;
                    }
                }

                CheckMergedObjectDefinition(mergedObjectDefinition, objectName, requiredType, arguments);

                // return IObjectDefinition instance itself for an abstract object-definition
                if (mergedObjectDefinition.IsAbstract)
                {
                    instance = mergedObjectDefinition;
                }
                else if (mergedObjectDefinition.IsSingleton)
                {
                    // create object instance...
                    object sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
                    instance = GetObjectForInstance(sharedInstance, name, objectName, mergedObjectDefinition);
                }
                else
                {
                    // it's a prototype, so create a new instance...
                    BeforePrototypeCreation(name);
                    try
                    {
                        instance = InstantiateObject(name, mergedObjectDefinition, arguments, true, suppressConfigure);
                    }
                    finally
                    {
                        AfterPrototypeCreation(name);
                    }
                }

                return EnsureObjectIsOfRequiredType(name, instance, requiredType);
            }
            catch
            {
                nestingCount--;
                hasErrors = true;
                #region Instrumentation
                if (log.IsErrorEnabled)
                {
                    log.Error(string.Format("{1}GetObjectInternal: error obtaining object {0}", name, new String(' ', nestingCount * INDENT)));
                }
                #endregion
                throw;
            }
            finally
            {
                if (!hasErrors)
                {
                    nestingCount--;
                    #region Instrumentation
                    if (log.IsDebugEnabled)
                    {
                        log.Debug(string.Format("{1}GetObjectInternal: returning instance for objectname {0}", name, new String(' ', nestingCount * INDENT)));
                    }
                    #endregion
                }
            }
        }

        [ThreadStatic]
        private int nestingCount;

        /// <summary>
        /// Checks, if the passed instance is of the required type.
        /// </summary>
        /// <param name="name">the name of the object</param>
        /// <param name="instance">the actual instance</param>
        /// <param name="requiredType">the type contract the given instance must adhere.</param>
        /// <returns>the object instance passed in via <paramref name="instance"/>(for more fluent usage)</returns>
        /// <exception cref="ObjectNotOfRequiredTypeException">
        /// if <paramref name="instance"/> is null or not assignable to <paramref name="requiredType"/>.
        /// </exception>
        private object EnsureObjectIsOfRequiredType(string name, object instance, Type requiredType)
        {           
            // check that any required type matches the type of the actual object instance...
            if (requiredType != null && instance!= null && !requiredType.IsAssignableFrom(instance.GetType()))
            {
                throw new ObjectNotOfRequiredTypeException(name, requiredType, instance);
            }

            return instance;
        }

        /// <summary>
        /// Creates a singleton instance for the specified object name and definition.
        /// </summary>
        /// <param name="objectName">
        /// The object name (will be used as the key in the singleton cache key).
        /// </param>
        /// <param name="objectDefinition">The object definition.</param>
        /// <param name="arguments">
        /// The arguments to use if creating a prototype using explicit arguments to
        /// a static factory method. If there is no factory method and the
        /// arguments are not null, then match the argument values by type and
        /// call the object's constructor.
        /// </param>
        /// <returns>The created object instance.</returns>
        protected virtual object CreateAndCacheSingletonInstance(string objectName,
                                                                 RootObjectDefinition objectDefinition,
                                                                 object[] arguments)
        {
            lock (singletonCache)
            {
                object sharedInstance = singletonCache[objectName];
                if (sharedInstance == null)
                {
                    #region Instrumentation
                    if (log.IsDebugEnabled)
                    {
                        log.Debug(string.Format("Creating shared instance of singleton object '{0}'", objectName));
                    }
                    #endregion

                    BeforeSingletonCreation(objectName);
                    try
                    {
                        sharedInstance = InstantiateObject(objectName, objectDefinition, arguments, true, false);
                    }
                    finally
                    {
                        AfterSingletonCreation(objectName);
                    }
                    AddSingleton(objectName, sharedInstance);

                    #region Instrumentation
                    if (log.IsDebugEnabled)
                    {
                        log.Debug(string.Format("Cached shared instance of singleton object '{0}'", objectName));
                    }
                    #endregion
                }
                return sharedInstance;
            }
        }

        /// <summary>
        /// Injects dependencies into the supplied <paramref name="target"/> instance
        /// using the named object definition.
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>
        public abstract object ConfigureObject(object target, string name);

        /// <summary>
        /// Injects dependencies into the supplied <paramref name="target"/> instance
        /// using the supplied <paramref name="definition"/>.
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>
        public abstract object ConfigureObject(object target, string name, IObjectDefinition definition);

        #endregion

        #endregion

        /// <summary>
        /// Destroy all cached singletons in this factory.
        /// </summary>
        public virtual void Dispose()
        {
            #region Instrumentation

            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format("Destroying singletons in factory [{0}].", this));
            }

            #endregion

            this.prototypesInCreation.Dispose();
            
            lock (singletonCache)
            {
                // copy the keys into a new set, 'cos we are going to modifying the
                // original collection (_singletonCache) as we destroy each singleton.
                ISet keys = new HashedSet(singletonCache.Keys);
                foreach (string name in keys)
                {
                    DestroySingleton(name);
                }
            }
        }

        /// <summary>
        /// Ignore the given dependency type for autowiring
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.Config.IConfigurableObjectFactory.IgnoreDependencyType"/>.
        public void IgnoreDependencyType(Type type)
        {
            IgnoredDependencyTypes.Add(type);
        }

        /// <summary>
        /// Determines whether the specified object name is currently in creation..
        /// </summary>
        /// <param name="objectName">Name of the object.</param>
        /// <returns>
        ///   <c>true</c> if the specified object name is currently in creation; otherwise, <c>false</c>.
        /// </returns>
        public bool IsCurrentlyInCreation(string objectName)
        {
            return IsSingletonCurrentlyInCreation(objectName) || IsPrototypeCurrentlyInCreation(objectName);
        }

        private void BeforePrototypeCreation(string name)
        {
            this.prototypesInCreation.Value.Add(name);
        }

        private void AfterPrototypeCreation(string name)
        {
            if (!IsPrototypeCurrentlyInCreation(name))
            {
                throw new InvalidOperationException("Singleton " + name + " isn't currently in creation.");
            }
            this.prototypesInCreation.Value.Remove(name);
        }

        private bool IsPrototypeCurrentlyInCreation(string name)
        {
            return this.prototypesInCreation.Value.Contains(name);
        }


        private void AfterSingletonCreation(string name)
        {
            if (!IsSingletonCurrentlyInCreation(name))
            {
                throw new InvalidOperationException("Singleton " + name + " isn't currently in creation.");
            }
            singletonsInCreation.Remove(name);
        }

        private void BeforeSingletonCreation(string name)
        {
            if (this.singletonsInCreation.Contains(name))
            {
                throw new ObjectCurrentlyInCreationException(name);
            }
            singletonsInCreation.Add(name, EMPTYOBJECT);
        }

        private bool IsSingletonCurrentlyInCreation(string name)
        {
            return this.singletonsInCreation.Contains(name);
        }

        /// <summary>
        /// Add a new <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>
        /// that will get applied to objects created by this factory.
        /// </summary>
        /// <param name="objectPostProcessor">
        /// The <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>
        /// to register.
        /// </param>
        /// <seealso cref="Spring.Objects.Factory.Config.IConfigurableObjectFactory.AddObjectPostProcessor"/>.
        public void AddObjectPostProcessor(IObjectPostProcessor objectPostProcessor)
        {
            if (objectPostProcessor is IObjectFactoryAware)
            {
                ((IObjectFactoryAware)objectPostProcessor).ObjectFactory = this;
            }

            // ensure the same instance doesn't get registered twice
            if (!ObjectPostProcessors.Contains(objectPostProcessor))
            {
                ObjectPostProcessors.Add(objectPostProcessor);
            }
            if (typeof(IInstantiationAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor))
            {
                hasInstantiationAwareBeanPostProcessors = true;
            }
            if (typeof(IDestructionAwareObjectPostProcessor).IsInstanceOfType(objectPostProcessor))
            {
                hasDestructionAwareBeanPostProcessors = true;
            }
        }

        /// <summary>
        /// Returns the current number of registered
        /// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>s.
        /// </summary>
        /// <value>
        /// The current number of registered
        /// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>s.
        /// </value>
        /// <seealso cref="Spring.Objects.Factory.Config.IConfigurableObjectFactory.ObjectPostProcessorCount"/>.
        public int ObjectPostProcessorCount
        {
            get { return ObjectPostProcessors.Count; }
        }

        /// <summary>
        /// Given an object name, create an alias.
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.Config.IConfigurableObjectFactory.RegisterAlias"/>.
        public void RegisterAlias(string name, string alias)
        {
            #region Sanity Checks

            AssertUtils.ArgumentHasText(name, "The object name must not be empty.");
            AssertUtils.ArgumentHasText(alias, "The alias must not be empty.");

            #endregion

            #region Instrumentation

            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format("Registering alias '{0}' for object with name '{1}'.", alias, name));
            }

            #endregion

            lock (aliasMap)
            {
                object registeredName = aliasMap[alias];
                if (registeredName != null)
                {
                    throw new ObjectDefinitionStoreException(
                            string.Format(
                                    "Cannot register alias '{0}' for object with name '{1}': it's already registered for object name '{2}'.",
                                    alias, name, registeredName));
                }
                aliasMap[alias] = name;
            }
        }

        /// <summary>
        /// Register the given custom <see cref="System.ComponentModel.TypeConverter"/>
        /// for all properties of the given <see cref="System.Type"/>.
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.Config.IConfigurableObjectFactory.RegisterCustomConverter"/>.
        public void RegisterCustomConverter(Type requiredType, TypeConverter converter)
        {
            AssertUtils.ArgumentNotNull(requiredType, "requiredType");
            TypeConverterRegistry.RegisterConverter(requiredType, converter);
        }

        #region ISingletonObjectRegistry Members

        /// <summary>
        /// Register the given existing object as singleton in the object factory,
        /// under the given object name.
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.Config.ISingletonObjectRegistry.RegisterSingleton"/>.
        public void RegisterSingleton(string name, object singletonObject)
        {
            AssertUtils.ArgumentHasText(name, "name", "The singleton object cannot be registered under an empty name.");
            lock (singletonCache)
            {
                object oldObject = singletonCache[name];
                if (oldObject != null)
                {
                    throw new ObjectDefinitionStoreException(
                            string.Format(
                                    "Could not register object [{0}] under object name '{1}': there's already object [{2}] bound.",
                                    singletonObject, name, oldObject));
                }
                AddSingleton(name, singletonObject);
            }
        }

        /// <summary>
        /// Does this object factory contains a singleton instance with the
        /// supplied <paramref name="name"/>?
        /// </summary>
        /// <seealso cref="Spring.Objects.Factory.Config.ISingletonObjectRegistry.ContainsSingleton(string)"/>
        public bool ContainsSingleton(string name)
        {
            AssertUtils.ArgumentHasText(name, "name");
            lock (singletonCache)
            {
                return singletonCache.Contains(name);
            }
        }

        /// <summary>
        /// Gets the names of singleton objects registered in this registry.
        /// </summary>
        /// <value>The list of names as String array (never <code>null</code>).</value>
        /// <remarks>
        ///   <para>
        /// Only checks already instantiated singletons; does not return names
        /// for singleton bean definitions which have not been instantiated yet.
        /// </para>
        ///   <para>
        /// The main purpose of this method is to check manually registered singletons
        /// <see cref="RegisterSingleton"/>. Can also be used to check which
        /// singletons defined by an object definition have already been created.
        /// </para>
        /// </remarks>
        /// <see cref="RegisterSingleton"/>
        /// <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry.GetObjectDefinitionNames"/>
        /// <see cref="Spring.Objects.Factory.IListableObjectFactory.GetObjectDefinitionNames"/>
        public string[] SingletonNames
        {
            get
            {
                lock (singletonCache)
                {
                    return
                        StringUtils.DelimitedListToStringArray(
                            StringUtils.CollectionToDelimitedString(registeredSingletons, ","), ",");

                }
            }
        }

        /// <summary>
        /// Gets the number of singleton beans registered in this registry.
        /// </summary>
        /// <value>The number of singleton objects.</value>
        /// <remarks>
        ///   <para>
        /// Only checks already instantiated singletons; does not count
        /// singleton object definitions which have not been instantiated yet.
        /// </para>
        ///   <para>
        /// The main purpose of this method is to check manually registered singletons
        /// <see cref="RegisterSingleton"/>.  Can also be used to count the number of
        /// singletons defined by an object definition that have already been created.
        /// </para>
        /// </remarks>
        /// <see cref="RegisterSingleton"/>
        /// <see cref="Spring.Objects.Factory.Support.IObjectDefinitionRegistry.ObjectDefinitionCount"/>
        /// <see cref="Spring.Objects.Factory.IListableObjectFactory.ObjectDefinitionCount"/>
        public int SingletonCount
        {
            get
            {
                lock (singletonCache)
                {
                    return registeredSingletons.Count;
                }
            }
        }
        /// <summary>
        /// Tries to find a cached object for the specified name. 
        /// </summary>
        /// <param name="objectName">Teh object name to look for.</param>
        /// <returns>The cached object if found, <see langword="null"/> otherwise.</returns>
        public virtual object GetSingleton(string objectName)
        {
            lock (singletonCache)
            {
                return singletonCache[objectName];
            }
        }

        #endregion


        /// <summary>
        /// Determines whether the given object name is already in use within this factory,
        /// i.e. whether there is a local object or alias registered under this name or
        /// an inner object created with this name.
        /// </summary>
        /// <param name="objectName">Name of the object to check.</param>
        /// <returns>
        ///   <c>true</c> if is object name in use; otherwise, <c>false</c>.
        /// </returns>
        public bool IsObjectNameInUse(string objectName)
        {
            return IsAlias(objectName) || ContainsLocalObject(objectName);
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.