AbstractApplicationContext.cs :  » Inversion-of-Control-Dependency-Injection » Spring.net » Spring » Context » 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 » Context » Support » AbstractApplicationContext.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.Diagnostics;
using System.Globalization;
using Common.Logging;
using Spring.Context.Events;
using Spring.Core;
using Spring.Core.IO;
using Spring.Objects;
using Spring.Objects.Events;
using Spring.Objects.Events.Support;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Support;
using Spring.Util;

#endregion

namespace Spring.Context.Support{
    /// <summary>
    /// Partial implementation of the
    /// <see cref="Spring.Context.IApplicationContext"/> interface.
    /// </summary>
    /// <remarks>
    /// <p>
    /// Does not mandate the type of storage used for configuration, but does
    /// implement common functionality. Uses the Template Method design
    /// pattern, requiring concrete subclasses to implement
    /// <see langword="abstract"/> methods.
    /// </p>
    /// <p>
    /// In contrast to a plain vanilla
    /// <see cref="Spring.Objects.Factory.IObjectFactory"/>, an
    /// <see cref="Spring.Context.IApplicationContext"/> is supposed
    /// to detect special objects defined in its object factory: therefore,
    /// this class automatically registers
    /// <see cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>s,
    /// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>s
    /// and <see cref="Spring.Context.IApplicationEventListener"/>s that are
    /// defined as objects in the context.
    /// </p>
    /// <p>
    /// An <see cref="Spring.Context.IMessageSource"/> may be also supplied as
    /// an object in the context, with the special, well-known-name of
    /// <c>"messageSource"</c>. Else, message resolution is delegated to the
    /// parent context.
    /// </p>
    /// </remarks>
    /// <author>Rod Johnson</author>
    /// <author>Juergan Hoeller</author>
    /// <author>Griffin Caprio (.NET)</author>
    /// <seealso cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>
    /// <seealso cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>
    public abstract class AbstractApplicationContext
        : ConfigurableResourceLoader, IConfigurableApplicationContext, IObjectDefinitionRegistry
    {
        #region Constants

        /// <summary>
        /// Name of the .Net config section that contains Spring.Net context definition.
        /// </summary>
        public const string ContextSectionName = "spring/context";

        /// <summary>
        /// Default name of the root context.
        /// </summary>
        public const string DefaultRootContextName = "spring.root";

        #endregion

        #region Fields

        private const long TicksAtEpoch = 621355968000000000;

        /// <summary>
        /// The special, well-known-name of the default
        /// <see cref="Spring.Context.IMessageSource"/> in the context.
        /// </summary>
        /// <remarks>
        /// <p>
        /// If no <see cref="Spring.Context.IMessageSource"/> can be found
        /// in the context using this lookup key, then message resolution
        /// will be delegated to the parent context (if any).
        /// </p>
        /// </remarks>
        public static readonly string MessageSourceObjectName = "messageSource";

        /// <summary>
        /// The special, well-known-name of the default
        /// <see cref="Spring.Objects.Events.IEventRegistry"/> in the context.
        /// </summary>
        /// <remarks>
        /// <p>
        /// If no <see cref="Spring.Objects.Events.IEventRegistry"/> can be found
        /// in the context using this lookup key, then a default
        /// <see cref="Spring.Objects.Events.IEventRegistry"/> will be used.
        /// </p>
        /// </remarks>
        public static readonly string EventRegistryObjectName = "eventRegistry";

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

        /// <summary>
        /// The <see cref="Spring.Context.IMessageSource"/> instance we delegate
        /// our implementation of said interface to.
        /// </summary>
        private IMessageSource _messageSource;

        /// <summary>
        /// The <see cref="Spring.Objects.Events.IEventRegistry"/> instance we
        /// delegate our implementation of said interface to.
        /// </summary>
        private IEventRegistry _eventRegistry;

        private IApplicationContext _parentApplicationContext;
        private readonly IList _objectFactoryPostProcessors;
        private readonly IList _defaultObjectPostProcessors;
        private string _name;
        private DateTime _startupDate;
        private readonly bool _isCaseSensitive;
        private EventRaiser _eventRaiser;

        #endregion


        #region Constructor (s) / Destructor

        /// <summary>
        /// Creates a new instance of the <see cref="AbstractApplicationContext"/>
        /// with no parent context.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes
        /// no public constructors.
        /// </p>
        /// </remarks>
        protected AbstractApplicationContext()
            : this(null, true, null)
        {
        }

        /// <summary>
        /// Creates a new instance of the <see cref="AbstractApplicationContext"/>
        /// with no parent context.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes
        /// no public constructors.
        /// </p>
        /// </remarks>
        /// <param name="caseSensitive">Flag specifying whether to make this context case sensitive or not.</param>
        protected AbstractApplicationContext(bool caseSensitive)
            : this(null, caseSensitive, null)
        {
        }

        /// <summary>
        /// Creates a new instance of the <see cref="AbstractApplicationContext"/>
        /// with the supplied parent context.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes
        /// no public constructors.
        /// </p>
        /// </remarks>
        /// <param name="name">The application context name.</param>
        /// <param name="caseSensitive">Flag specifying whether to make this context case sensitive or not.</param>
        /// <param name="parentApplicationContext">The parent application context.</param>
        protected AbstractApplicationContext(string name, bool caseSensitive,
                                             IApplicationContext parentApplicationContext)
        {
            log = LogManager.GetLogger(this.GetType());

            _name = (StringUtils.IsNullOrEmpty(name)) ? DefaultRootContextName : name;
            _isCaseSensitive = caseSensitive;
            _parentApplicationContext = parentApplicationContext;
            EventRaiser = CreateEventRaiser();
            _objectFactoryPostProcessors = new ArrayList();
            _defaultObjectPostProcessors = new ArrayList();
            AddDefaultObjectPostProcessor(new ObjectPostProcessorChecker());
            AddDefaultObjectPostProcessor(new ApplicationContextAwareProcessor(this));
            AddDefaultObjectPostProcessor(new SharedStateAwareProcessor(new ISharedStateFactory[] { new ByTypeSharedStateFactory() }, Int32.MaxValue));
        }

        /// <summary>
        /// Adds the given <see cref="IObjectPostProcessor"/> to the list of standard
        /// processors being added to the underlying <see cref="IConfigurableObjectFactory"/>
        /// </summary>
        /// <remarks>
        /// Each time <see cref="Refresh()"/> is called on this context, the context ensures, that 
        /// all default <see cref="IObjectPostProcessor"/>s are registered with the underlying <see cref="IConfigurableObjectFactory"/>.
        /// </remarks>
        /// <param name="defaultObjectPostProcessor">The <see cref="IObjectPostProcessor"/> instance.</param>
        protected void AddDefaultObjectPostProcessor(IObjectPostProcessor defaultObjectPostProcessor)
        {
            _defaultObjectPostProcessors.Add(defaultObjectPostProcessor);
        }

        /// <summary>
        /// Closes this context and disposes of any resources (such as
        /// singleton objects in the wrapped
        /// <see cref="Spring.Objects.Factory.IObjectFactory"/>).
        /// </summary>
        public virtual void Dispose()
        {
            GC.SuppressFinalize(this);

            #region Instrumentation

            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format(
                              CultureInfo.InvariantCulture,
                              "Closing application context [{0}].",
                              Name));
            }

            #endregion

            // Closed event is raised before destroying objectfactory to enable registered IApplicationEventListeners 
            // to handle the event before they get disposed.
            PublishEvent(this, new ContextClosedEventArgs());

            ObjectFactory.Dispose();
        }

        #endregion

        #region Abstract Methods

        /// <summary>
        /// Subclasses must implement this method to perform the actual
        /// configuration loading.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This method is invoked by
        /// <see cref="Spring.Context.Support.AbstractApplicationContext.Refresh()"/>,
        /// before any other initialization occurs.
        /// </p>
        /// </remarks>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// In the case of errors encountered while refreshing the object factory.
        /// </exception>
        protected abstract void RefreshObjectFactory();

        #endregion

        /// <summary>
        /// An object that can be used to synchronize access to the <see cref="AbstractXmlApplicationContext"/>
        /// </summary>
        public object SyncRoot
        {
            get { return this; }
        }

        /// <summary>
        /// Set the <see cref="EventRaiser"/> to be used by this context.
        /// </summary>
        public EventRaiser EventRaiser
        {
            set
            {
                AssertUtils.ArgumentNotNull(value, "EventRaiser");
                _eventRaiser = value;
            }
        }

        /// <summary>
        /// The timestamp when this context was first loaded.
        /// </summary>
        /// <returns>
        /// The timestamp (milliseconds) when this context was first loaded.
        /// </returns>
        public long StartupDateMilliseconds
        {
            get { return (StartupDate.Ticks - TicksAtEpoch) / 10000; }
        }


        /// <summary>
        /// Gets a flag indicating whether context should be case sensitive.
        /// </summary>
        /// <value><c>true</c> if object lookups are case sensitive; otherwise, <c>false</c>.</value>
        public bool IsCaseSensitive
        {
            get { return _isCaseSensitive; }
        }

        /// <summary>
        /// The <see cref="Spring.Context.IMessageSource"/> for this context.
        /// </summary>
        /// <exception cref="System.InvalidOperationException">
        /// If the context has not been initialized yet.
        /// </exception>
        public IMessageSource MessageSource
        {
            get
            {
                if (_messageSource == null)
                {
                    throw new InvalidOperationException(
                        "MessageSource not initialized - call 'Refresh()' " +
                        "before accessing messages via the context: " + this);
                }
                return _messageSource;
            }
        }

        /// <summary>
        /// The <see cref="Spring.Objects.Events.IEventRegistry"/> for this context.
        /// </summary>
        /// <exception cref="System.InvalidOperationException">
        /// If the context has not been initialized yet.
        /// </exception>
        public IEventRegistry EventRegistry
        {
            get
            {
                if (_eventRegistry == null)
                {
                    throw new InvalidOperationException(
                        "EventRegistry not initialized - call 'Refresh()' " +
                        "before accessing the event registry via the context: " + this);
                }
                return _eventRegistry;
            }
        }

        /// <summary>
        /// Returns the internal object factory of the parent context if it implements
        /// <see cref="Spring.Context.IConfigurableApplicationContext"/>; else,
        /// returns the parent context itself.
        /// </summary>
        /// <returns>
        /// The parent context's object factory, or the parent itself.
        /// </returns>
        protected IObjectFactory GetInternalParentObjectFactory()
        {
            IConfigurableApplicationContext configContext
                = _parentApplicationContext as IConfigurableApplicationContext;
            if (configContext != null)
            {
                return ((IConfigurableApplicationContext)
                        _parentApplicationContext).ObjectFactory;
            }
            else
            {
                return _parentApplicationContext;
            }
        }

        /// <summary>
        /// Raises an application context event.
        /// </summary>
        /// <param name="e">
        /// Any arguments to the event. May be <see langword="null"/>.
        /// </param>
        protected virtual void OnContextEvent(ApplicationEventArgs e)
        {
            OnContextEvent(this, e);
        }

        /// <summary>
        /// Raises an application context event.
        /// </summary>
        /// <param name="source">
        /// The source of the event.
        /// </param>
        /// <param name="e">
        /// Any arguments to the event. May be <see langword="null"/>.
        /// </param>
        protected virtual void OnContextEvent(object source, ApplicationEventArgs e)
        {
            IEventExceptionsCollector exceptions = _eventRaiser.Raise(ContextEvent, source, e);
            if (exceptions.HasExceptions)
            {
                Delegate target = ContextEvent.GetInvocationList()[0];
                Exception exception = (Exception) exceptions[target];
                throw new ApplicationContextException(string.Format("An unhandled exception occured during processing application event {0} in handler {1}", e.GetType(), target.Method), exception);
            }
        }

        /// <summary>
        /// Create the <see cref="EventRaiser"/> strategy to be used
        /// </summary>
        protected virtual EventRaiser CreateEventRaiser()
        {
            return new DefensiveEventRaiser();
        }

        /// <summary>
        /// Modify the application context's internal object factory after its standard
        /// initialization.
        /// </summary>
        /// <remarks>
        /// <p>
        /// All object definitions will have been loaded, but no objects
        /// will have been instantiated yet. This allows for the registration
        /// of special
        /// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>s
        /// in certain
        /// <see cref="Spring.Context.IApplicationContext"/> implementations.
        /// </p>
        /// </remarks>
        /// <param name="objectFactory">
        /// The object factory used by the application context.
        /// </param>
        /// <exception cref="ObjectsException">
        /// In the case of errors.
        /// </exception>.
        protected virtual void PostProcessObjectFactory(
            IConfigurableListableObjectFactory objectFactory)
        {
        }

        /// <summary>
        /// Template method which can be overridden to add context-specific
        /// work before the underlying object factory gets refreshed.
        /// </summary>
        protected virtual void OnPreRefresh()
        {
        }

        /// <summary>
        /// Template method which can be overridden to add context-specific
        /// refresh work.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Called on initialization of special objects, before instantiation
        /// of singletons.
        /// </p>
        /// </remarks>
        protected virtual void OnRefresh()
        {
        }

        /// <summary>
        /// Template method which can be overridden to add context-specific
        /// work after the context was refreshed but before the <see cref="ContextEventArgs.ContextEvent.Refreshed"/>
        /// event gets raised.
        /// </summary>
        protected virtual void OnPostRefresh()
        {
            PublishEvent(this, new ContextRefreshedEventArgs());
        }

        /// <summary>
        /// Instantiate and invoke all registered
        /// <see cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>
        /// objects, respecting any explicit ordering.
        /// </summary>
        /// <remarks>
        /// <note type="caution">
        /// <b>Must</b> be called before singleton instantiation.
        /// </note>
        /// </remarks>
        /// <exception cref="ObjectsException">In the case of errors.</exception>
        private void InvokeObjectFactoryPostProcessors()
        {
            // do NOT include IFactoryObjects; they (typically) need to be instantiated
            // to determine the Type of object that they create, and if they are instantiated
            // then we won't be able to do any factory post processin' on 'em...
            string[] factoryProcessorNames
                = GetObjectNamesForType(typeof(IObjectFactoryPostProcessor), true, false);
            ArrayList orderedFactoryProcessors = new ArrayList();
            IList nonOrderedFactoryProcessorNames = new ArrayList();
            for (int i = 0; i < factoryProcessorNames.Length; ++i)
            {
                string processorName = factoryProcessorNames[i];
                object processor = GetObject(processorName);
                if (typeof(IOrdered).IsAssignableFrom(GetType(processorName)))
                {
                    orderedFactoryProcessors.Add(processor);
                }
                else
                {
                    nonOrderedFactoryProcessorNames.Add(processor);
                }
            }
            // first, invoke those IObjectFactoryPostProcessors that implement IOrdered...
            orderedFactoryProcessors.Sort(new OrderComparator());
            ProcessObjectFactoryPostProcessors(orderedFactoryProcessors);
            // and then the unordered ones...
            ProcessObjectFactoryPostProcessors(nonOrderedFactoryProcessorNames);

            #region Instrumentation

            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format(
                              CultureInfo.InvariantCulture,
                              "processed {0} IFactoryObjectPostProcessors defined in application context [{1}].",
                              factoryProcessorNames.Length,
                              Name));
            }

            #endregion
        }

        private void ProcessObjectFactoryPostProcessors(IList objectFactoryPostProcessors)
        {
            foreach (IObjectFactoryPostProcessor processor in objectFactoryPostProcessors)
            {
                processor.PostProcessObjectFactory(ObjectFactory);
            }
        }

        private void RegisterObjectPostProcessors(IConfigurableListableObjectFactory objectFactory)
        {
            RefreshObjectPostProcessorChecker(objectFactory);
            IDictionary dict = GetObjectsOfType(typeof(IObjectPostProcessor), true, false);
            ArrayList objectProcessors = new ArrayList(dict.Values);
            //            objectProcessors.Sort(new OrderComparator());
            foreach (IObjectPostProcessor objectPostProcessor in objectProcessors)
            {
                ObjectFactory.AddObjectPostProcessor(objectPostProcessor);
            }

            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format(
                              CultureInfo.InvariantCulture,
                              "processed {0} IObjectPostProcessors defined in application context [{1}].",
                              objectProcessors.Count,
                              Name));
            }
        }

        /// <summary>
        /// Resets the well-known ObjectPostProcessorChecker that logs an info
        /// message when an object is created during IObjectPostProcessor
        /// instantiation, i.e. when an object is not eligible for being
        /// processed by all IObjectPostProcessors.
        /// </summary>
        private void RefreshObjectPostProcessorChecker(IConfigurableListableObjectFactory objectFactory)
        {
            int registeredObjectPostProcessorCount = GetObjectNamesForType(typeof(IObjectPostProcessor), true, false).Length;
            int objectPostProcessorCount = ObjectFactory.ObjectPostProcessorCount + 1
                                           + registeredObjectPostProcessorCount;
            ((ObjectPostProcessorChecker)_defaultObjectPostProcessors[0]).Reset(objectFactory, objectPostProcessorCount);
        }

        /// <summary>
        /// Initializes the default event registry for this context.
        /// </summary>
        private void InitEventRegistry()
        {
            if (ContainsLocalObject(EventRegistryObjectName))
            {
                object candidateRegistry = GetObject(EventRegistryObjectName);
                if (candidateRegistry is IEventRegistry)
                {
                    _eventRegistry = (IEventRegistry)candidateRegistry;

                    #region Instrumentation

                    log.Debug(StringUtils.Surround(
                                  "Using IEventRegistry [", EventRegistry, "]"));

                    #endregion
                }
                else
                {
                    _eventRegistry = new EventRegistry();

                    #region Instrumentation

                    if (log.IsWarnEnabled)
                    {
                        log.Warn(string.Format(
                                     "Found object in context named '{0}' : this name " +
                                     "is typically reserved for IEventRegistry objects. " +
                                     "Falling back to default '{1}'.",
                                     EventRegistryObjectName, EventRegistry));
                    }

                    #endregion
                }
            }
            else
            {
                _eventRegistry = new EventRegistry();

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format(
                                  "No IEventRegistry found with name '{0}' : using default '{1}'.",
                                  EventRegistryObjectName, EventRegistry));
                }

                #endregion
            }
            ICollection interestedParties
                = GetObjectsOfType(typeof(IEventRegistryAware), true, false).Values;
            foreach (IEventRegistryAware party in interestedParties)
            {
                party.EventRegistry = EventRegistry;
            }
            EventRegistry.PublishEvents(this);
        }

        /// <summary>
        /// Returns the internal message source of the parent context if said
        /// parent context is an <see cref="AbstractApplicationContext"/>, else
        /// simply the parent context itself.
        /// </summary>
        /// <returns>
        /// The internal message source of the parent context if said
        /// parent context is an <see cref="AbstractApplicationContext"/>, else
        /// simply the parent context itself.
        /// </returns>
        protected virtual IMessageSource GetInternalParentMessageSource()
        {
            AbstractApplicationContext parent
                = ParentContext as AbstractApplicationContext;
            return parent == null ? ParentContext : parent._messageSource;
        }

        /// <summary>
        /// Initializes the default message source for this context.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Uses any parent context's message source if one is not available
        /// in this context.
        /// </p>
        /// </remarks>
        private void InitMessageSource()
        {
            if (ContainsLocalObject(MessageSourceObjectName))
            {
                object candidateSource = GetObject(MessageSourceObjectName);
                if (candidateSource is IMessageSource)
                {
                    _messageSource
                        = (IMessageSource)GetObject(MessageSourceObjectName);

                    // make IMessageSource aware of any parent IMessageSource...
                    if (ParentContext != null)
                    {
                        IHierarchicalMessageSource hierSource
                            = MessageSource as IHierarchicalMessageSource;
                        if (hierSource != null)
                        {
                            IMessageSource parentMessageSource
                                = GetInternalParentMessageSource();
                            hierSource.ParentMessageSource = parentMessageSource;
                        }
                    }

                    #region Instrumentation

                    if (log.IsDebugEnabled)
                    {
                        log.Debug(StringUtils.Surround(
                                      "Using MessageSource [", MessageSource, "]"));
                    }

                    #endregion
                }
                else
                {
                    _messageSource = new DelegatingMessageSource(
                        GetInternalParentMessageSource());

                    #region Instrumentation

                    if (log.IsWarnEnabled)
                    {
                        log.Warn(string.Format(
                                     "Found object in context named '{0}' : this name " +
                                     "is typically reserved for IMessageSource objects. " +
                                     "Falling back to default '{1}'.",
                                     MessageSourceObjectName, MessageSource));
                    }

                    #endregion
                }
            }
            else if (ParentContext != null)
            {
                _messageSource = new DelegatingMessageSource(
                    GetInternalParentMessageSource());
                ObjectFactory.RegisterSingleton(MessageSourceObjectName, _messageSource);

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format(
                                  "No message source found in the current context: using parent context's message source '{0}'.",
                                  MessageSource));
                }

                #endregion
            }
            else
            {
                _messageSource = new StaticMessageSource();
                ObjectFactory.RegisterSingleton(MessageSourceObjectName, _messageSource);

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format(
                                  "No IMessageSource found with name '{0}' : using default '{1}'.",
                                  MessageSourceObjectName, MessageSource));
                }

                #endregion
            }
        }

        private void RefreshApplicationEventListeners()
        {
            ICollection listeners
                = GetObjectsOfType(
                    typeof(IApplicationEventListener), true, false).Values;
            foreach (IApplicationEventListener applicationListener in listeners)
            {
                EventRegistry.Subscribe(applicationListener);
            }
        }

        /// <summary>
        /// Returns the list of the
        /// <see cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>s
        /// that will be applied to the objects created with this factory.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The elements of this list are instances of implementations of the
        /// <see cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>
        /// interface.
        /// </p>
        /// </remarks>
        /// <value>
        /// The list of the
        /// <see cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>s
        /// that will be applied to the objects created with this factory.
        /// </value>
        private IList ObjectFactoryPostProcessors
        {
            get { return _objectFactoryPostProcessors; }
        }

        #region IConfigurableApplicationContext Members

        /// <summary>
        /// Return the internal object factory of this application context.
        /// </summary>
        public abstract IConfigurableListableObjectFactory ObjectFactory { get; }

        /// <summary>
        /// Add a new <see cref="Spring.Objects.Factory.Config.IObjectFactoryPostProcessor"/>
        /// that will get applied to the internal object factory of this application context
        /// on refresh, before any of the object definitions are evaluated.
        /// </summary>
        /// <param name="objectFactoryPostProcessor">
        /// The factory processor to register.
        /// </param>
        public void AddObjectFactoryPostProcessor(
            IObjectFactoryPostProcessor objectFactoryPostProcessor)
        {
            _objectFactoryPostProcessors.Add(objectFactoryPostProcessor);
        }

        /// <summary>
        /// Load or refresh the persistent representation of the configuration,
        /// which might an XML file, properties file, or relational database schema.
        /// </summary>
        /// <exception cref="Spring.Context.ApplicationContextException">
        /// If the configuration cannot be loaded.
        /// </exception>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the object factory could not be initialized.
        /// </exception>
        public void Refresh()
        {
            lock (SyncRoot)
            {
                _startupDate = DateTime.Now;

                OnPreRefresh();

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("ApplicationContext Refresh: Refreshing object factory "));
                }

                #endregion

                RefreshObjectFactory();

                IConfigurableListableObjectFactory objectFactory = ObjectFactory;

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("ApplicationContext Refresh: Registering well-known processors and objects"));
                }

                #endregion

                PrepareObjectFactory(objectFactory);

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("ApplicationContext Refresh: Custom post processing object factory"));
                }

                #endregion

                PostProcessObjectFactory(objectFactory);

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("ApplicationContext Refresh: Post processing object factory using pre-registered processors"));
                }

                #endregion

                foreach (IObjectFactoryPostProcessor factoryProcessor in ObjectFactoryPostProcessors)
                {
                    factoryProcessor.PostProcessObjectFactory(objectFactory);
                }

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format(
                                  CultureInfo.InvariantCulture,
                                  "{0} objects defined in application context [{1}].",
                                  ObjectDefinitionCount == 0 ? "No" : ObjectDefinitionCount.ToString(),
                                  Name));
                }

                #endregion

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("ApplicationContext Refresh: Post processing object factory using defined processors"));
                }

                #endregion

                InvokeObjectFactoryPostProcessors();

                RegisterObjectPostProcessors(objectFactory);
                InitEventRegistry();
                InitMessageSource();

                RefreshApplicationEventListeners();

                OnRefresh();

                #region Instrumentation

                if (log.IsDebugEnabled)
                {
                    log.Debug(string.Format("ApplicationContext Refresh: Preinstantiating singletons"));
                }

                #endregion

                objectFactory.PreInstantiateSingletons();

                OnPostRefresh();

                #region Instrumentation

                if (log.IsInfoEnabled)
                {
                    log.Info(string.Format("ApplicationContext Refresh: Completed"));
                }

                #endregion
            }
        }

        /// <summary>
        /// Registers well-known <see cref="IObjectPostProcessor"/>s and 
        /// preregisters well-known dependencies using <see cref="IConfigurableListableObjectFactory.RegisterResolvableDependency"/>
        /// </summary>
        /// <param name="objectFactory">the raw object factory as returned from <see cref="RefreshObjectFactory"/></param>
        private void PrepareObjectFactory(IConfigurableListableObjectFactory objectFactory)
        {
            EnsureKnownObjectPostProcessors(objectFactory);
            objectFactory.IgnoreDependencyType(typeof(IResourceLoader));
            objectFactory.IgnoreDependencyType(typeof(IApplicationContext));

            objectFactory.RegisterResolvableDependency(typeof(IObjectFactory), objectFactory);
            objectFactory.RegisterResolvableDependency(typeof(IResourceLoader), this);
            objectFactory.RegisterResolvableDependency(typeof(IApplicationEventPublisher), this);
            objectFactory.RegisterResolvableDependency(typeof(IApplicationContext), this);
            objectFactory.RegisterResolvableDependency(typeof(IEventRegistry), this);
        }

        /// <summary>
        /// Ensures, that predefined ObjectPostProcessors are registered with this ObjectFactory
        /// </summary>
        /// <param name="objectFactory"></param>
        protected void EnsureKnownObjectPostProcessors(IConfigurableListableObjectFactory objectFactory)
        {
            // index 0 contains the ObjectPostProcessorChecker that is handled separately!
            for (int i = 1; i < _defaultObjectPostProcessors.Count; i++)
            {
                objectFactory.AddObjectPostProcessor((IObjectPostProcessor)this._defaultObjectPostProcessors[i]);
            }
        }

        /// <summary>
        /// Gets the parent context, or <see langword="null"/> if there is no
        /// parent context.
        /// </summary>
        /// <returns>
        /// The parent context, or <see langword="null"/>  if there is no
        /// parent.
        /// </returns>
        /// <seealso cref="Spring.Context.IApplicationContext.ParentContext"/>
        public virtual IApplicationContext ParentContext
        {
            get { return _parentApplicationContext; }
            set { _parentApplicationContext = value; }
        }

        #endregion

        #region ILifecycle Members

        /// <summary>
        /// Starts this component.
        /// </summary>
        /// <remarks>Should not throw an exception if the component is already running.
        /// In the case of a container, this will propagate the start signal
        /// to all components that apply.
        /// </remarks>
        public void Start()
        {
            IDictionary lifecycleObjects = LifeCycleObjects;
            foreach (DictionaryEntry dictionaryEntry in lifecycleObjects)
            {
                //TODO start dependencies of the lifecycle objects
                ILifecycle obj = dictionaryEntry.Value as ILifecycle;
                if (obj != null)
                {
                    if (!obj.IsRunning)
                    {
                        obj.Start();
                    }
                }
            }
        }

        /// <summary>
        /// Stops this component.
        /// </summary>
        /// <remarks>
        /// Should not throw an exception if the component isn't started yet.
        /// In the case of a container, this will propagate the stop signal
        /// to all components that apply.
        /// </remarks>
        public void Stop()
        {
            IDictionary lifecycleObjects = LifeCycleObjects;
            foreach (DictionaryEntry dictionaryEntry in lifecycleObjects)
            {
                //TODO stop dependencies of the lifecycle objects
                ILifecycle obj = dictionaryEntry.Value as ILifecycle;
                if (obj != null)
                {
                    if (obj.IsRunning)
                    {
                        obj.Stop();
                    }
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether this component is currently running.
        /// </summary>
        /// <value>
        ///   <c>true</c> if this component is running; otherwise, <c>false</c>.
        /// </value>
        /// <remarks>
        /// In the case of a container, this will return <code>true</code>
        /// only if <i>all</i> components that apply are currently running.
        /// </remarks>
        public bool IsRunning
        {
            get
            {
                IDictionary lifecycleObjects = LifeCycleObjects;
                foreach (DictionaryEntry dictionaryEntry in lifecycleObjects)
                {
                    ILifecycle obj = dictionaryEntry.Value as ILifecycle;
                    if (obj != null)
                    {
                        if (!obj.IsRunning)
                        {
                            return false;
                        }
                    }
                }
                return true;
            }
        }

        /// <summary>
        /// Gets a dictionary of all singleton beans that implement the
        /// ILifecycle interface in this context.
        /// </summary>
        /// <value>A dictionary of ILifecycle objects with object name as key.</value>
        private IDictionary LifeCycleObjects
        {
            get
            {
                IConfigurableListableObjectFactory objectFactory = ObjectFactory;
                string[] objectNames = objectFactory.SingletonNames;
                IDictionary lifeCycleObjects = new Hashtable();
                foreach (string objectName in objectNames)
                {
                    object obj = objectFactory.GetSingleton(objectName);
                    if (obj is ILifecycle)
                    {
                        lifeCycleObjects[objectName] = obj;
                    }
                }
                return lifeCycleObjects;
            }
        }

        #endregion

        #region IApplicationContext Members

        /// <summary>
        /// Raised in response to an implementation-dependant application
        /// context event.
        /// </summary>
        public event ApplicationEventHandler ContextEvent;

        /// <summary>
        /// The date and time this context was first loaded.
        /// </summary>
        /// <returns>
        /// The <see cref="System.DateTime"/> representing when this context
        /// was first loaded.
        /// </returns>
        public DateTime StartupDate
        {
            get { return _startupDate; }
        }

        /// <summary>
        /// A name for this context.
        /// </summary>
        /// <returns>
        /// A name for this context.
        /// </returns>
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }



        #endregion

        #region IListableObjectFactory Members

        /// <summary>
        /// Return the names of objects matching the given <see cref="System.Type"/>
        /// (including subclasses), judging from the object definitions.
        /// </summary>
        /// <param name="type">
        /// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
        /// for all object names.
        /// </param>
        /// <returns>
        /// The names of all objects defined in this factory, or an empty array if none
        /// are defined.
        /// </returns>
        /// <seealso cref="Spring.Objects.Factory.IListableObjectFactory.GetObjectNamesForType(Type)"/>
        public string[] GetObjectNamesForType(Type type)
        {
            return ObjectFactory.GetObjectNamesForType(type);
        }

        /// <summary>
        /// Return the names of objects matching the given <see cref="System.Type"/>
        /// (including subclasses), judging from the object definitions.
        /// </summary>
        /// <param name="type">
        /// The <see cref="System.Type"/> (class or interface) to match, or <see langword="null"/>
        /// for all object names.
        /// </param>
        /// <param name="includePrototypes">
        /// Whether to include prototype objects too or just singletons (also applies to
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
        /// </param>
        /// <param name="includeFactoryObjects">
        /// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
        /// or just normal objects.
        /// </param>
        /// <returns>
        /// The names of all objects defined in this factory, or an empty array if none
        /// are defined.
        /// </returns>
        /// <seealso cref="Spring.Objects.Factory.IListableObjectFactory.GetObjectNamesForType(Type, bool, bool)"/>
        public string[] GetObjectNamesForType(
            Type type, bool includePrototypes, bool includeFactoryObjects)
        {
            return ObjectFactory.GetObjectNamesForType(type, includePrototypes, includeFactoryObjects);
        }

        /// <summary>
        /// Return the names of all objects defined in this factory.
        /// </summary>
        /// <returns>
        /// The names of all objects defined in this factory, or an empty array if none
        /// are defined.
        /// </returns>
        /// <seealso cref="Spring.Objects.Factory.IListableObjectFactory.GetObjectDefinitionNames()"/>
        public string[] GetObjectDefinitionNames()
        {
            return ObjectFactory.GetObjectDefinitionNames();
        }

        /// <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 virtual IObjectDefinition GetObjectDefinition(string name)
        {
            return ObjectFactory.GetObjectDefinition(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 IObjectDefinition GetObjectDefinition(string name, bool includeAncestors)
        {
            return ObjectFactory.GetObjectDefinition(name, includeAncestors);
        }

        /// <summary>
        /// Return the object instances that match the given object
        /// <see cref="System.Type"/> (including subclasses), judging from either object
        /// definitions or the value of
        /// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
        /// </summary>
        /// <param name="type">
        /// The <see cref="System.Type"/> (class or interface) to match.
        /// </param>
        /// <returns>
        /// A <see cref="System.Collections.IDictionary"/> of the matching objects,
        /// containing the object names as keys and the corresponding object instances
        /// as values.
        /// </returns>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the objects could not be created.
        /// </exception>
        /// <seealso cref="Spring.Objects.Factory.IListableObjectFactory.GetObjectsOfType(Type)"/>
        public IDictionary GetObjectsOfType(Type type)
        {
            return GetObjectsOfType(type, true, true);
        }

        /// <summary>
        /// Return the object instances that match the given object
        /// <see cref="System.Type"/> (including subclasses), judging from either object
        /// definitions or the value of
        /// <see cref="Spring.Objects.Factory.IFactoryObject.ObjectType"/> in the case of
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
        /// </summary>
        /// <param name="type">
        /// The <see cref="System.Type"/> (class or interface) to match.
        /// </param>
        /// <param name="includePrototypes">
        /// Whether to include prototype objects too or just singletons (also applies to
        /// <see cref="Spring.Objects.Factory.IFactoryObject"/>s).
        /// </param>
        /// <param name="includeFactoryObjects">
        /// Whether to include <see cref="Spring.Objects.Factory.IFactoryObject"/>s too
        /// or just normal objects.
        /// </param>
        /// <returns>
        /// A <see cref="System.Collections.IDictionary"/> of the matching objects,
        /// containing the object names as keys and the corresponding object instances
        /// as values.
        /// </returns>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the objects could not be created.
        /// </exception>
        /// <seealso cref="Spring.Objects.Factory.IListableObjectFactory.GetObjectsOfType(Type, bool, bool)"/>
        public IDictionary GetObjectsOfType(
            Type type, bool includePrototypes, bool includeFactoryObjects)
        {
            return ObjectFactory.GetObjectsOfType(type, includePrototypes, includeFactoryObjects);
        }

        /// <summary>
        /// Return the number of objects defined in the factory.
        /// </summary>
        /// <value>
        /// The number of objects defined in the factory.
        /// </value>
        /// <seealso cref="Spring.Objects.Factory.IListableObjectFactory.ObjectDefinitionCount"/>
        public int ObjectDefinitionCount
        {
            get { return ObjectFactory.ObjectDefinitionCount; }
        }

        /// <summary>
        /// Check if this object factory contains an object definition with the given name.
        /// </summary>
        /// <param name="name">The name of the object to look for.</param>
        /// <returns>
        /// True if this object factory contains an object definition with the given name.
        /// </returns>
        /// <seealso cref="Spring.Objects.Factory.IListableObjectFactory.ContainsObjectDefinition(string)"/>
        public bool ContainsObjectDefinition(string name)
        {
            return ObjectFactory.ContainsObjectDefinition(name);
        }

        #endregion

        #region IObjectFactory Members

        /// <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>
        /// <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>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/>
        public object this[string name]
        {
            get { return ObjectFactory.GetObject(name); }
        }

        /// <summary>
        /// Does this object factory contain an object with the given name?
        /// </summary>
        /// <param name="name">The name of the object to query.</param>
        /// <returns>
        /// <see langword="true"/> if an object with the given name is defined.
        /// </returns>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.ContainsObject(string)"/>
        public bool ContainsObject(string name)
        {
            return ObjectFactory.ContainsObject(name);
        }

        /// <summary>
        /// Return the aliases for the given object name, if defined.
        /// </summary>
        /// <param name="name">The object name to check for aliases.</param>
        /// <returns>The aliases, or an empty array if none.</returns>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there's no such object definition.
        /// </exception>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetAliases(string)"/>
        public string[] GetAliases(string name)
        {
            return ObjectFactory.GetAliases(name);
        }


        /// <summary>
        /// Return an unconfigured(!) 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 unconfigured(!) 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="IObjectFactory.CreateObject"/>
        /// <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 ObjectFactory.CreateObject(name, requiredType, arguments);
        }

        /// <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">
        /// <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>
        /// <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>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type)"/>
        public object GetObject(string name, Type requiredType)
        {
            return ObjectFactory.GetObject(name, requiredType);
        }

        /// <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>
        /// <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>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/>
        public object GetObject(string name)
        {
            return ObjectFactory.GetObject(name);
        }

        /// <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 ObjectFactory.GetObject(name, arguments);
        }

        /// <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, object[])"/>
        public object GetObject(string name, Type requiredType, object[] arguments)
        {
            return ObjectFactory.GetObject(name, requiredType, arguments);
        }

        /// <summary>
        /// Is this object a singleton?
        /// </summary>
        /// <param name="name">The name of the object to query.</param>
        /// <returns>True if the named object is a singleton.</returns>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there's no such object definition.
        /// </exception>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.IsSingleton(string)"/>
        public bool IsSingleton(string name)
        {
            return ObjectFactory.IsSingleton(name);
        }

        /// <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)
        {
            return ObjectFactory.IsPrototype(name);
        }


        /// <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)
        {
            return ObjectFactory.IsTypeMatch(name, targetType);
        }

        /// <summary>
        /// Determine the <see cref="System.Type"/>  of the object with the
        /// given name.
        /// </summary>
        /// <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>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetType(string)"/>
        public Type GetType(string name)
        {
            return ObjectFactory.GetType(name);
        }

        /// <summary>
        /// Injects dependencies into the supplied <paramref name="target"/> instance
        /// using the named object definition.
        /// </summary>
        /// <param name="target">
        /// The object instance that is to be so configured.
        /// </param>
        /// <param name="name">
        /// The name of the object definition expressing the dependencies that are to
        /// be injected into the supplied <parameref name="target"/> instance.
        /// </param>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>
        public object ConfigureObject(object target, string name)
        {
            return ObjectFactory.ConfigureObject(target, name);
        }

        /// <summary>
        /// Injects dependencies into the supplied <paramref name="target"/> instance
        /// using the supplied <paramref name="definition"/>.
        /// </summary>
        /// <param name="target">
        /// The object instance that is to be so configured.
        /// </param>
        /// <param name="name">
        /// The name of the object definition expressing the dependencies that are to
        /// be injected into the supplied <parameref name="target"/> instance.
        /// </param>
        /// <param name="definition">
        /// An object definition that should be used to configure object.
        /// </param>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>
        public object ConfigureObject(object target, string name, IObjectDefinition definition)
        {
            return ObjectFactory.ConfigureObject(target, name, definition);
        }

        #endregion

        #region IHierarchicalObjectFactory Members

        /// <summary>
        /// Return 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>
        /// <seealso cref="Spring.Objects.Factory.IHierarchicalObjectFactory.ParentObjectFactory"/>
        public IObjectFactory ParentObjectFactory
        {
            get { return _parentApplicationContext; }
        }

        /// <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>
        /// <remarks>
        /// 
        /// </remarks>
        /// <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)
        {
            return ObjectFactory.ContainsLocalObject(name);
        }

        #endregion

        #region IObjectDefinitionRegistry Members

        /// <summary>
        /// Determine whether the given object name is already in use within this context, 
        /// i.e. whether there is a local object. May be override by subclasses, the default 
        /// implementation simply returns <see cref="ContainsLocalObject"/>
        /// </summary>
        public virtual bool IsObjectNameInUse(string objectName)
        {
            return ContainsLocalObject(objectName);
        }

        /// <summary>
        /// Register a new object definition with this registry.
        /// Must support
        /// <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/>
        /// and <see cref="Spring.Objects.Factory.Support.ChildObjectDefinition"/>.
        /// </summary>
        /// <param name="name">The name of the object instance to register.</param>
        /// <param name="definition">The definition of the object instance to register.</param>
        /// <remarks>
        ///   <p>
        /// Must support
        /// <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/> and
        /// <see cref="Spring.Objects.Factory.Support.ChildObjectDefinition"/>.
        /// </p>
        /// </remarks>
        /// <exception cref="Spring.Objects.ObjectsException">
        /// If the object definition is invalid.
        /// </exception>
        public virtual void RegisterObjectDefinition(string name, IObjectDefinition definition)
        {
            ObjectFactory.RegisterObjectDefinition(name, definition);
        }

        /// <summary>
        /// Given a object name, create an alias. We typically use this method to
        /// support names that are illegal within XML ids (used for object names).
        /// </summary>
        /// <param name="name">The name of the object.</param>
        /// <param name="theAlias">The alias that will behave the same as the object name.</param>
        /// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
        /// If there is no object with the given name.
        /// </exception>
        /// <exception cref="Spring.Objects.Factory.ObjectDefinitionStoreException">
        /// If the alias is already in use.
        /// </exception>
        public virtual void RegisterAlias(string name, string theAlias)
        {
            ObjectFactory.RegisterAlias(name, theAlias);
        }

        #endregion

        #region IMessageSource Members

        /// <summary>
        /// Resolve the message identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the message to resolve.</param>
        /// <param name="culture">
        /// The <see cref="System.Globalization.CultureInfo"/> that represents
        /// the culture for which the resource is localized.
        /// </param>
        /// <param name="arguments">
        /// The array of arguments that will be filled in for parameters within
        /// the message, or <see langword="null"/> if there are no parameters
        /// within the message. Parameters within a message should be
        /// referenced using the same syntax as the format string for the
        /// <see cref="System.String.Format(string,object[])"/> method.
        /// </param>
        /// <returns>
        /// The resolved message if the lookup was successful (see above for
        /// the return value in the case of an unsuccessful lookup).
        /// </returns>
        /// <exception cref="Spring.Context.NoSuchMessageException">
        /// If no message could be resolved.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="name"/> is <see langword="null"/>.
        /// </exception>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(string, CultureInfo, object[])"/>
        public string GetMessage(
            string name, CultureInfo culture, params object[] arguments)
        {
            return MessageSource.GetMessage(name, culture, arguments);
        }

        /// <summary>
        /// Resolve the message identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the message to resolve.</param>
        /// <param name="defaultMessage">The default message.</param>
        /// <param name="culture">
        /// The <see cref="System.Globalization.CultureInfo"/> that represents
        /// the culture for which the resource is localized.
        /// </param>
        /// <param name="arguments">
        /// The array of arguments that will be filled in for parameters within
        /// the message, or <see langword="null"/> if there are no parameters
        /// within the message. Parameters within a message should be
        /// referenced using the same syntax as the format string for the
        /// <see cref="System.String.Format(string,object[])"/> method.
        /// </param>
        /// <returns>
        /// The resolved message if the lookup was successful (see above for
        /// the return value in the case of an unsuccessful lookup).
        /// </returns>
        /// <exception cref="Spring.Context.NoSuchMessageException">
        /// If no message could be resolved.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="name"/> is <see langword="null"/>.
        /// </exception>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(string, CultureInfo, object[])"/>
        public string GetMessage(string name, string defaultMessage, CultureInfo culture, params object[] arguments)
        {
            return MessageSource.GetMessage(name, defaultMessage, culture, arguments);
        }

        /// <summary>
        /// Resolve the message identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the message to resolve.</param>
        /// <returns>
        /// The resolved message if the lookup was successful.
        /// </returns>
        /// <exception cref="Spring.Context.NoSuchMessageException">
        /// If no message could be resolved.
        /// </exception>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(string)"/>
        public string GetMessage(string name)
        {
            return MessageSource.GetMessage(name);
        }

        /// <summary>
        /// Resolve the message identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the message to resolve.</param>
        /// <param name="arguments">
        /// The array of arguments that will be filled in for parameters within
        /// the message, or <see langword="null"/> if there are no parameters
        /// within the message. Parameters within a message should be
        /// referenced using the same syntax as the format string for the
        /// <see cref="System.String.Format(string,object[])"/> method.
        /// </param>
        /// <returns>
        /// The resolved message if the lookup was successful.
        /// </returns>
        /// <exception cref="Spring.Context.NoSuchMessageException">
        /// If no message could be resolved.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="name"/> is <see langword="null"/>.
        /// </exception>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(string, object[])"/>
        public string GetMessage(string name, params object[] arguments)
        {
            return MessageSource.GetMessage(name, arguments);
        }

        /// <summary>
        /// Resolve the message identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">The name of the message to resolve.</param>
        /// <param name="culture">
        /// The <see cref="System.Globalization.CultureInfo"/> that represents
        /// the culture for which the resource is localized.
        /// </param>
        /// <returns>
        /// The resolved message if the lookup was successful (see above for
        /// the return value in the case of an unsuccessful lookup).
        /// </returns>
        /// <exception cref="Spring.Context.NoSuchMessageException">
        /// If no message could be resolved.
        /// </exception>
        /// <exception cref="System.ArgumentNullException">
        /// If the supplied <paramref name="name"/> is <see langword="null"/>.
        /// </exception>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(string, CultureInfo)"/>
        public string GetMessage(string name, CultureInfo culture)
        {
            return MessageSource.GetMessage(name, culture);
        }

        /// <summary>
        /// Resolve the message using all of the attributes contained within
        /// the supplied <see cref="Spring.Context.IMessageSourceResolvable"/>
        /// argument.
        /// </summary>
        /// <param name="resolvable">
        /// The value object storing those attributes that are required to
        /// properly resolve a message.
        /// </param>
        /// <param name="culture">
        /// The <see cref="System.Globalization.CultureInfo"/> that represents
        /// the culture for which the resource is localized.
        /// </param>
        /// <returns>
        /// The resolved message if the lookup was successful (see above for
        /// the return value in the case of an unsuccessful lookup).
        /// </returns>
        /// <exception cref="Spring.Context.NoSuchMessageException">
        /// If the message could not be resolved.
        /// </exception>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(IMessageSourceResolvable, CultureInfo)"/>
        public string GetMessage(IMessageSourceResolvable resolvable, CultureInfo culture)
        {
            return MessageSource.GetMessage(resolvable, culture);
        }

        /// <summary>
        /// Gets a localized resource object identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">
        /// The name of the resource object to resolve.
        /// </param>
        /// <param name="culture">
        /// The <see cref="System.Globalization.CultureInfo"/> with which the
        /// resource is associated.
        /// </param>
        /// <returns>
        /// The resolved object, or <see langword="null"/> if not found.
        /// </returns>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(string, CultureInfo)"/>
        object IMessageSource.GetResourceObject(string name, CultureInfo culture)
        {
            return GetResourceObject(name, culture);
        }

        /// <summary>
        /// Gets a localized resource object identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">
        /// The name of the resource object to resolve.
        /// </param>
        /// <returns>
        /// The resolved object, or <see langword="null"/> if not found.
        /// </returns>
        /// <seealso cref="Spring.Context.IMessageSource.GetMessage(string)"/>
        object IMessageSource.GetResourceObject(string name)
        {
            return GetResourceObject(name);
        }

        /// <summary>
        /// Gets a localized resource object identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">
        /// The name of the resource object to resolve.
        /// </param>
        /// <param name="culture">
        /// The <see cref="System.Globalization.CultureInfo"/> with which the
        /// resource is associated.
        /// </param>
        /// <returns>
        /// The resolved object, or <see langword="null"/> if not found.
        /// </returns>
        /// <seealso cref="Spring.Context.IMessageSource.GetResourceObject(string, CultureInfo)"/>
        public object GetResourceObject(string name, CultureInfo culture)
        {
            return MessageSource.GetResourceObject(name, culture);
        }

        /// <summary>
        /// Gets a localized resource object identified by the supplied
        /// <paramref name="name"/>.
        /// </summary>
        /// <param name="name">
        /// The name of the resource object to resolve.
        /// </param>
        /// <returns>
        /// The resolved object, or <see langword="null"/> if not found.
        /// </returns>
        /// <seealso cref="Spring.Context.IMessageSource.GetResourceObject(string)"/>
        public object GetResourceObject(string name)
        {
            return MessageSource.GetResourceObject(name);
        }

        /// <summary>
        /// Applies resources to object properties.
        /// </summary>
        /// <param name="value">
        /// An object that contains the property values to be applied.
        /// </param>
        /// <param name="objectName">
        /// The base name of the object to use for key lookup.
        /// </param>
        /// <param name="culture">
        /// The <see cref="System.Globalization.CultureInfo"/> with which the
        /// resource is associated.
        /// </param>
        /// <seealso cref="Spring.Context.IMessageSource.ApplyResources(object, string, CultureInfo)"/>
        public void ApplyResources(object value, string objectName, CultureInfo culture)
        {
            MessageSource.ApplyResources(value, objectName, culture);
        }

        #endregion

        #region IEventRegistry Members

        /// <summary>
        /// Publishes <b>all</b> events of the source object.
        /// </summary>
        /// <param name="sourceObject">
        /// The source object containing events to publish.
        /// </param>
        /// <seealso cref="Spring.Objects.Events.IEventRegistry.PublishEvents"/>
        public void PublishEvents(object sourceObject)
        {
            _eventRegistry.PublishEvents(sourceObject);
        }

        /// <summary>
        /// Subscribes to <b>all</b> events published, if the subscriber
        /// implements compatible handler methods.
        /// </summary>
        /// <param name="subscriber">The subscriber to use.</param>
        /// <seealso cref="Spring.Objects.Events.IEventRegistry.Subscribe(object)"/>
        public void Subscribe(object subscriber)
        {
            _eventRegistry.Subscribe(subscriber);
        }

        /// <summary>
        /// Subscribes to published events of a all objects of a given
        /// <see cref="System.Type"/>, if the subscriber implements
        /// compatible handler methods.
        /// </summary>
        /// <param name="subscriber">The subscriber to use.</param>
        /// <param name="targetSourceType">
        /// The target <see cref="System.Type"/> to subscribe to.
        /// </param>
        /// <seealso cref="Spring.Objects.Events.IEventRegistry.Subscribe(object, Type)"/>
        public void Subscribe(object subscriber, Type targetSourceType)
        {
            _eventRegistry.Subscribe(subscriber, targetSourceType);
        }


        /// <summary>
        /// Unsubscribes to <b>all</b> events published, if the subscriber
        /// implmenets compatible handler methods.
        /// </summary>
        /// <param name="subscriber">The subscriber to use</param>
        public void Unsubscribe(object subscriber)
        {
            _eventRegistry.Unsubscribe(subscriber);
        }

        /// <summary>
        /// Unsubscribes to the published events of all objects of a given
        /// <see cref="System.Type"/>, if the subscriber implements
        /// compatible handler methods.
        /// </summary>
        /// <param name="subscriber">The subscriber to use.</param>
        /// <param name="targetSourceType">
        /// The target <see cref="System.Type"/> to unsubscribe from
        /// </param>
        public void Unsubscribe(object subscriber, Type targetSourceType)
        {
            _eventRegistry.Unsubscribe(subscriber, targetSourceType);
        }

        #endregion

        #region IApplicationEventPublisher

        /// <summary>
        /// Publishes an application context event.
        /// </summary>
        /// <remarks>
        /// <p>
        /// 
        /// </p>
        /// </remarks>
        /// <param name="sender">
        /// The source of the event. May be <see langword="null"/>.
        /// </param>
        /// <param name="e">
        /// The event that is to be raised.
        /// </param>
        /// <seealso cref="Spring.Context.IApplicationEventPublisher.PublishEvent"/>
        public void PublishEvent(object sender, ApplicationEventArgs e)
        {
            #region Instrumentation

            if (log.IsDebugEnabled)
            {
                log.Debug(string.Format(
                              CultureInfo.InvariantCulture,
                              "Publishing event in context [{0}] : {1}",
                              Name, e));
            }

            #endregion

            OnContextEvent(sender, e);

            if (ParentContext != null)
            {
                ParentContext.PublishEvent(sender, e);
            }
        }

        #endregion

        #region IPostProcessor implementation

        private sealed class ObjectPostProcessorChecker : IObjectPostProcessor, IOrdered
        {
            private readonly ILog log;
            private int _objectPostProcessorTargetCount;
            private IConfigurableListableObjectFactory _objectFactory;


            public ObjectPostProcessorChecker()
            {
                log = LogManager.GetLogger(this.GetType());
            }

            public void Reset(IConfigurableListableObjectFactory objectFactory, int objectPostProcessorTargetCount)
            {
                _objectFactory = objectFactory;
                _objectPostProcessorTargetCount = objectPostProcessorTargetCount;
            }

            public object PostProcessBeforeInitialization(object obj, string name)
            {
                return obj;
            }

            public object PostProcessAfterInitialization(object obj, string objectName)
            {
                if (_objectFactory.ObjectPostProcessorCount < _objectPostProcessorTargetCount)
                {
                    #region Instrumentation

                    if (log.IsInfoEnabled)
                    {
                        log.Info(string.Format(
                                     "Object '{0}' is not eligible for being processed by all " +
                                     "IObjectPostProcessors (for example: not eligible for auto-proxying).", objectName));
                    }

                    #endregion
                }
                return obj;
            }

            public int Order
            {
                get { return Int32.MinValue; }
            }
        }

        #endregion
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.