#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.Globalization;
using System.Reflection;
using System.Text;
using Spring.Core;
using Spring.Core.TypeResolution;
using Spring.Objects.Factory.Config;
using Spring.Util;

#endregion

namespace Spring.Objects.Factory.Support
{
    /// <summary>
    /// Common base class for object definitions, factoring out common
    /// functionality from
    /// <see cref="Spring.Objects.Factory.Support.RootObjectDefinition"/> and
    /// <see cref="Spring.Objects.Factory.Support.ChildObjectDefinition"/>.
    /// </summary>
    /// <author>Rod Johnson</author>
    /// <author>Juergen Hoeller</author>
    /// <author>Rick Evans (.NET)</author>
    [Serializable]
    public abstract class AbstractObjectDefinition : IConfigurableObjectDefinition
    {
        private static readonly string SCOPE_SINGLETON = "singleton";
        private static readonly string SCOPE_PROTOTYPE = "prototype";

        #region Constructor (s) / Destructor

        /// <summary>
        /// Creates a new instance of the
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectDefinition"/>
        /// class.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes no
        /// public constructors.
        /// </p>
        /// </remarks>
        protected AbstractObjectDefinition() : this(null, null)
        {
        }

        /// <summary>
        /// Creates a new instance of the
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectDefinition"/>
        /// class.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes no
        /// public constructors.
        /// </p>
        /// </remarks>
        protected AbstractObjectDefinition(ConstructorArgumentValues arguments, MutablePropertyValues properties)
        {
            constructorArgumentValues =
                (arguments != null) ? arguments : new ConstructorArgumentValues();
            propertyValues =
                (properties != null) ? properties : new MutablePropertyValues();
            eventHandlerValues = new EventValues();
            DependsOn = StringUtils.EmptyStrings;
        }

        /// <summary>
        /// Creates a new instance of the
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectDefinition"/>
        /// class.
        /// </summary>
        /// <param name="other">
        /// The object definition used to initialise the member fields of this
        /// instance.
        /// </param>
        /// <remarks>
        /// <p>
        /// This is an <see langword="abstract"/> class, and as such exposes no
        /// public constructors.
        /// </p>
        /// </remarks>
        protected AbstractObjectDefinition(IObjectDefinition other)
        {
            AssertUtils.ArgumentNotNull(other, "other");
            this.OverrideFrom(other);

            AbstractObjectDefinition aod = other as AbstractObjectDefinition;
            if (aod != null)
            {
                if (aod.HasObjectType)
                {
                    ObjectType = other.ObjectType;
                }
                else
                {
                    ObjectTypeName = other.ObjectTypeName;
                }
                MethodOverrides = new MethodOverrides(aod.MethodOverrides);
                DependencyCheck = aod.DependencyCheck;
            }
            ParentName = other.ParentName;
            IsAbstract = other.IsAbstract;
//            IsSingleton = other.IsSingleton;
            Scope = other.Scope;
            Role = other.Role;
            IsLazyInit = other.IsLazyInit;
            ConstructorArgumentValues
                = new ConstructorArgumentValues(other.ConstructorArgumentValues);
            PropertyValues = new MutablePropertyValues(other.PropertyValues);
            EventHandlerValues = new EventValues(other.EventHandlerValues);

            InitMethodName = other.InitMethodName;
            DestroyMethodName = other.DestroyMethodName;
            DependsOn = new string[other.DependsOn.Length];
            IsAutowireCandidate = other.IsAutowireCandidate;
            Array.Copy(other.DependsOn, DependsOn, other.DependsOn.Length);
            FactoryMethodName = other.FactoryMethodName;
            FactoryObjectName = other.FactoryObjectName;
            AutowireMode = other.AutowireMode;
            ResourceDescription = other.ResourceDescription;
        }

        #endregion

        #region Properties

        /// <summary>
        /// The name of the parent definition of this object definition, if any.
        /// </summary>
        public abstract string ParentName { get; set; }

        /// <summary>
        /// The property values that are to be applied to the object
        /// upon creation.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Setting the value of this property to <see langword="null"/>
        /// will merely result in a new (and empty)
        /// <see cref="Spring.Objects.MutablePropertyValues"/>
        /// collection being assigned to the property value.
        /// </p>
        /// </remarks>
        /// <value>
        /// The property values (if any) for this object; may be an
        /// empty collection but is guaranteed not to be
        /// <see langword="null"/>.
        /// </value>
        public MutablePropertyValues PropertyValues
        {
            get { return propertyValues; }
            set { propertyValues = value == null ? new MutablePropertyValues() : value; }
        }

        /// <summary>
        /// Does this definition have any
        /// <see cref="Spring.Objects.Factory.Support.MethodOverrides"/>?
        /// </summary>
        /// <value>
        /// <see langword="true"/> if this definition has at least one
        /// <see cref="Spring.Objects.Factory.Support.MethodOverride"/>.
        /// </value>
        public bool HasMethodOverrides
        {
            get { return !MethodOverrides.IsEmpty; }
        }

        /// <summary>
        /// The constructor argument values for this object.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Setting the value of this property to <see langword="null"/>
        /// will merely result in a new (and empty)
        /// <see cref="Spring.Objects.Factory.Config.ConstructorArgumentValues"/>
        /// collection being assigned.
        /// </p>
        /// </remarks>
        /// <value>
        /// The constructor argument values (if any) for this object; may be an
        /// empty collection but is guaranteed not to be
        /// <see langword="null"/>.
        /// </value>
        public ConstructorArgumentValues ConstructorArgumentValues
        {
            get { return constructorArgumentValues; }
            set { constructorArgumentValues = value == null ? new ConstructorArgumentValues() : value; }
        }

        /// <summary>
        /// The event handler values for this object.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Setting the value of this property to <see langword="null"/>
        /// will merely result in a new (and empty)
        /// <see cref="Spring.Objects.Factory.Config.EventValues"/>
        /// collection being assigned.
        /// </p>
        /// </remarks>
        /// <value>
        /// The event handler values (if any) for this object; may be an
        /// empty collection but is guaranteed not to be
        /// <see langword="null"/>.
        /// </value>
        public EventValues EventHandlerValues
        {
            get { return eventHandlerValues; }
            set { eventHandlerValues = value == null ? new EventValues() : value; }
        }

        /// <summary>
        /// The method overrides (if any) for this object.
        /// </summary>
        /// <remarks>
        /// <p>
        /// Setting the value of this property to <see langword="null"/>
        /// will merely result in a new (and empty)
        /// <see cref="Spring.Objects.Factory.Support.MethodOverrides"/>
        /// collection being assigned to the property value.
        /// </p>
        /// </remarks>
        /// <value>
        /// The method overrides (if any) for this object; may be an
        /// empty collection but is guaranteed not to be
        /// <see langword="null"/>.
        /// </value>
        public MethodOverrides MethodOverrides
        {
            get { return methodOverrides; }
            set { methodOverrides = value == null ? new MethodOverrides() : value; }
        }

        /// <summary>
        /// The name of the target scope for the object.
        /// Defaults to "singleton", ootb alternative is "prototype". Extended object factories
        /// might support further scopes.
        /// </summary>
        public virtual string Scope
        {
            get { return scope; }
            set
            {
                AssertUtils.ArgumentNotNull(value, "Scope");
                this.scope = value;
                this.isPrototype = 0 == string.Compare(SCOPE_PROTOTYPE, value, true);
                this.isSingleton = !isPrototype; // 0 == string.Compare(SCOPE_SINGLETON, value, true);
            }
        }

        /// <summary>
        /// Get or set the role hint for this object definition
        /// </summary>
        public virtual ObjectRole Role
        {
            get { return role; }
            set { role = value; }
        }

        /// <summary>
        /// Is this definition a <b>singleton</b>, with
        /// a single, shared instance returned on all calls to an enclosing
        /// container (typically an
        /// <see cref="Spring.Objects.Factory.IObjectFactory"/> or
        /// <see cref="Spring.Context.IApplicationContext"/>).
        /// </summary>
        /// <remarks>
        /// <p>
        /// If <see langword="false"/>, an object factory will apply the
        /// <b>prototype</b> design pattern, with each caller requesting an
        /// instance getting an independent instance. How this is defined
        /// will depend on the object factory implementation. <b>singletons</b>
        /// are the commoner type.
        /// </p>
        /// </remarks>
        /// <seealso cref="Spring.Objects.Factory.IObjectFactory"/>
        public virtual bool IsSingleton
        {
            get { return isSingleton; }
            set
            {
                scope = (value ? SCOPE_SINGLETON : SCOPE_PROTOTYPE);
                isSingleton = value;
                isPrototype = !value;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is prototype, with an independent instance
        /// returned for each call.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is prototype; otherwise, <c>false</c>.
        /// </value>
        public virtual bool IsPrototype
        {
            get { return isPrototype; }
        }

        /// <summary>
        /// Is this object lazily initialized?</summary>
        /// <remarks>
        /// <p>
        /// Only applicable to a singleton object.
        /// </p>
        /// <p>
        /// If <see langword="false"/>, it will get instantiated on startup
        /// by object factories that perform eager initialization of
        /// singletons.
        /// </p>
        /// </remarks>
        public bool IsLazyInit
        {
            get { return isLazyInit; }
            set { isLazyInit = value; }
        }

        /// <summary>
        /// Is this object definition a "template", i.e. not meant to be instantiated
        /// itself but rather just serving as an object definition for configuration 
        /// templates used by <see cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>.
        /// </summary>
        /// <value>
        /// <see langword="true"/> if this object definition is a "template".
        /// </value>
        public bool IsTemplate
        {
            get
            {
                return (
                           isAbstract ||
                           (objectType == null && StringUtils.IsNullOrEmpty(factoryObjectName))
                       );
            }
        }

        /// <summary>
        /// Is this object definition "abstract", i.e. not meant to be
        /// instantiated itself but rather just serving as a parent for concrete
        /// child object definitions.
        /// </summary>
        /// <value>
        /// <see langword="true"/> if this object definition is "abstract".
        /// </value>
        public bool IsAbstract
        {
            get { return isAbstract; }
            set { isAbstract = value; }
        }

        /// <summary>
        /// The <see cref="System.Type"/> of the object definition (if any).
        /// </summary>
        /// <value>
        /// A resolved object <see cref="System.Type"/>.
        /// </value>
        /// <exception cref="ApplicationException">
        /// If the <see cref="System.Type"/> of the object definition is not a
        /// resolved <see cref="System.Type"/> or <see langword="null"/>.
        /// </exception>
        /// <seealso cref="AbstractObjectDefinition.HasObjectType"/>
        public Type ObjectType
        {
            get
            {
                if (!HasObjectType)
                {
                    throw new ApplicationException(
                        "Object definition does not carry a resolved System.Type");
                }
                return (Type) objectType;
            }
            set { objectType = value; }
        }

        /// <summary>
        /// Is the <see cref="System.Type"/> of the object definition a resolved
        /// <see cref="System.Type"/>?
        /// </summary>
        public bool HasObjectType
        {
            get { return objectType is Type; }
        }

        /// <summary>
        /// Returns the <see cref="System.Type.FullName"/> of the
        /// <see cref="System.Type"/> of the object definition (if any).
        /// </summary>
        public string ObjectTypeName
        {
            get
            {
                if (objectType is Type)
                {
                    return ((Type) objectType).FullName;
                }
                else
                {
                    return objectType as string;
                }
            }
            set { objectType = StringUtils.GetTextOrNull(value); }
        }


        /// <summary>
        /// A description of the resource that this object definition
        /// came from (for the purpose of showing context in case of errors).
        /// </summary>
        public string ResourceDescription
        {
            get { return resourceDescription; }
            set { resourceDescription = StringUtils.GetTextOrNull(value); }
        }

        /// <summary>
        /// The autowire mode as specified in the object definition.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This determines whether any automagical detection and setting of
        /// object references will happen. The default is
        /// <see cref="Spring.Objects.Factory.Config.AutoWiringMode.No"/>,
        /// which means that no autowiring will be performed.
        /// </p>
        /// </remarks>
        public AutoWiringMode AutowireMode
        {
            get { return autowireMode; }
            set { autowireMode = value; }
        }

        /// <summary>
        /// Gets the resolved autowire mode.
        /// </summary>
        /// <remarks>
        /// <p>
        /// This resolves
        /// <see cref="Spring.Objects.Factory.Config.AutoWiringMode.AutoDetect"/>
        /// to one of 
        /// <see cref="Spring.Objects.Factory.Config.AutoWiringMode.Constructor"/>
        /// or
        /// <see cref="Spring.Objects.Factory.Config.AutoWiringMode.ByType"/>.
        /// </p>
        /// </remarks>
        public AutoWiringMode ResolvedAutowireMode
        {
            get
            {
                if (AutowireMode == AutoWiringMode.AutoDetect)
                {
                    // Work out whether to apply setter autowiring or constructor autowiring.
                    // If it has a no-arg constructor it's deemed to be setter autowiring,
                    // otherwise we'll try constructor autowiring.
                    ConstructorInfo[] constructors =
                        ObjectType.GetConstructors();
                    foreach (ConstructorInfo ctor in constructors)
                    {
                        if (ctor.GetParameters().Length == 0)
                        {
                            return AutoWiringMode.ByType;
                        }
                    }
                    return AutoWiringMode.Constructor;
                }
                else
                {
                    return AutowireMode;
                }
            }
        }

        /// <summary>
        /// The dependency checking mode.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The default is
        /// <see cref="Spring.Objects.Factory.Support.DependencyCheckingMode.None"/>.
        /// </p>
        /// </remarks>
        public DependencyCheckingMode DependencyCheck
        {
            get { return dependencyCheck; }
            set { dependencyCheck = value; }
        }

        /// <summary>
        /// The object names that this object depends on.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The object factory will guarantee that these objects get initialized
        /// before this object definition.
        /// </p>
        /// <note>
        /// Dependencies are normally expressed through object properties
        /// or constructor arguments. This property should just be necessary for
        /// other kinds of dependencies such as statics (*ugh*) or database
        /// preparation on startup.
        /// </note>
        /// </remarks>
        public string[] DependsOn
        {
            get { return dependsOn; }
            set { dependsOn = value == null ? StringUtils.EmptyStrings : value; }
        }

        /// <summary>
        /// Gets or sets a value indicating whether this instance a candidate for getting autowired into some other
        /// object.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if this instance is autowire candidate; otherwise, <c>false</c>.
        /// </value>
        public bool IsAutowireCandidate
        {
            get { return autowireCandidate; }
            set { autowireCandidate = value;}
        }

        /// <summary>
        /// The name of the initializer method.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The default value is the <see cref="String.Empty"/> constant,
        /// in which case there is no initializer method.
        /// </p>
        /// </remarks>
        public string InitMethodName
        {
            get { return initMethodName; }
            set { initMethodName = StringUtils.GetTextOrNull(value); }
        }

        /// <summary>
        /// Return the name of the destroy method.
        /// </summary>
        /// <remarks>
        /// <p>
        /// The default value is the <see cref="String.Empty"/> constant,
        /// in which case there is no destroy method.
        /// </p>
        /// </remarks>
        public string DestroyMethodName
        {
            get { return destroyMethodName; }
            set { destroyMethodName = StringUtils.GetTextOrNull(value); }
        }

        /// <summary>
        /// The name of the factory method to use (if any).
        /// </summary>
        /// <remarks>
        /// <p>
        /// This method will be invoked with constructor arguments, or with no
        /// arguments if none are specified. The <see langword="static"/>
        /// method will be invoked on the specified
        /// <see cref="Spring.Objects.Factory.Config.IObjectDefinition.ObjectType"/>.
        /// </p>
        /// </remarks>
        public string FactoryMethodName
        {
            get { return factoryMethodName; }
            set { factoryMethodName = StringUtils.GetTextOrNull(value); }
        }

        /// <summary>
        /// The name of the factory object to use (if any).
        /// </summary>
        public string FactoryObjectName
        {
            get { return factoryObjectName; }
            set { factoryObjectName = StringUtils.GetTextOrNull(value); }
        }

        /// <summary>
        /// Does this object definition have any constructor argument values?
        /// </summary>
        /// <value>
        /// <see langword="true"/> if his object definition has at least one
        /// element in it's
        /// <see cref="Spring.Objects.Factory.Support.AbstractObjectDefinition.ConstructorArgumentValues"/>
        /// property.
        /// </value>
        public virtual bool HasConstructorArgumentValues
        {
            get
            {
                return ConstructorArgumentValues != null
                       && !ConstructorArgumentValues.Empty;
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Resolves the type of the object, resolving it from a specified
        /// object type name if necessary. 
        /// </summary>
        /// <returns>
        /// A resolved <see cref="System.Type"/> instance.
        /// </returns>
        /// <exception cref="System.TypeLoadException">
        /// If the type cannot be resolved.
        /// </exception>
        public Type ResolveObjectType()
        {
            string typeName = ObjectTypeName;
            if (typeName == null)
            {
                return null;
            }
            Type resolvedType = TypeResolutionUtils.ResolveType(typeName);
            this.ObjectType = resolvedType;
            return resolvedType;
        }

        /// <summary>
        /// Validate this object definition.
        /// </summary>
        /// <exception cref="Spring.Objects.Factory.Support.ObjectDefinitionValidationException">
        /// In the case of a validation failure.
        /// </exception>
        public virtual void Validate()
        {
            if (IsLazyInit && !IsSingleton)
            {
                throw new ObjectDefinitionValidationException(
                    "Lazy initialization is only applicable to singleton objects.");
            }
            if (HasMethodOverrides && StringUtils.HasText(FactoryMethodName))
            {
                throw new ObjectDefinitionValidationException(
                    "Cannot combine static factory method with method overrides: " +
                    "the static factory method must create the instance.");
            }
            if (HasObjectType)
            {
                PrepareMethodOverrides();
            }
        }

        /// <summary>
        /// Validates all <see cref="MethodOverrides"/> 
        /// </summary>
        public virtual void PrepareMethodOverrides()
        {
            // ascertain that the various lookup methods exist...
            foreach (MethodOverride mo in MethodOverrides.Overrides)
            {
                PrepareMethodOverride(mo);
            }
        }

        /// <summary>
        /// Validate the supplied <paramref name="methodOverride"/>.
        /// </summary>
        /// <param name="methodOverride">
        /// The <see cref="Spring.Objects.Factory.Support.MethodOverride"/>
        /// to be validated.
        /// </param>
        protected void PrepareMethodOverride(MethodOverride methodOverride)
        {
            if (!ReflectionUtils.HasAtLeastOneMethodWithName(ObjectType, methodOverride.MethodName))
            {
                throw new ObjectDefinitionValidationException(
                    string.Format(
                        CultureInfo.InvariantCulture,
                        "Invalid method override: no method with name '{0}' on class [{1}].",
                        methodOverride.MethodName, ObjectTypeName));
            }
            //TODO investigate setting overloaded at this point using MethodCountForName...
            //Test SunnyDayReplaceMethod_WithArgumentAcceptingReplacerWithNoTypeFragmentsSpecified
            // will fail if doing this optimization.
        }

        /// <summary>
        /// Override settings in this object definition from the supplied
        /// <paramref name="other"/> object definition.
        /// </summary>
        /// <param name="other">
        /// The object definition used to override the member fields of this instance.
        /// </param>
        public virtual void OverrideFrom(IObjectDefinition other)
        {
            AssertUtils.ArgumentNotNull(other, "other");

            IsAbstract = other.IsAbstract;
            Scope = other.Scope;
            IsLazyInit = other.IsLazyInit;
            ConstructorArgumentValues.AddAll(other.ConstructorArgumentValues);
            PropertyValues.AddAll(other.PropertyValues.PropertyValues);
            EventHandlerValues.AddAll(other.EventHandlerValues);
            if (StringUtils.HasText(other.ObjectTypeName))
            {
                ObjectTypeName = other.ObjectTypeName;
            }
            if (StringUtils.HasText(other.InitMethodName))
            {
                InitMethodName = other.InitMethodName;
            }
            if (StringUtils.HasText(other.DestroyMethodName))
            {
                DestroyMethodName = other.DestroyMethodName;
            }
            if (StringUtils.HasText(other.FactoryObjectName))
            {
                FactoryObjectName = other.FactoryObjectName;
            }
            if (StringUtils.HasText(other.FactoryMethodName))
            {
                FactoryMethodName = other.FactoryMethodName;
            }
            if (ArrayUtils.HasLength(other.DependsOn))
            {
                ArrayList deps = new ArrayList(other.DependsOn);
                if (ArrayUtils.HasLength(DependsOn))
                {
                    deps.AddRange(DependsOn);
                }
                DependsOn = (string[]) deps.ToArray(typeof(string));
            }
            AutowireMode = other.AutowireMode;
            ResourceDescription = other.ResourceDescription;

            AbstractObjectDefinition aod = other as AbstractObjectDefinition;
            if (aod != null)
            {
                if (aod.HasObjectType)
                {
                    ObjectType = other.ObjectType;
                }

                MethodOverrides.AddAll(aod.MethodOverrides);
                DependencyCheck = aod.DependencyCheck;
            }
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents the current
        /// <see cref="System.Object"/>. 
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents the current
        /// <see cref="System.Object"/>. 
        /// </returns>
        public override string ToString()
        {
            StringBuilder buffer = new StringBuilder(string.Format("Class [{0}]", ObjectTypeName));
            buffer.Append("; Abstract = ").Append(IsAbstract);
            buffer.Append("; Parent = ").Append(ParentName);
            buffer.Append("; Scope = ").Append(Scope);
            buffer.Append("; Singleton = ").Append(IsSingleton);
            buffer.Append("; LazyInit = ").Append(IsLazyInit);
            buffer.Append("; Autowire = ").Append(AutowireMode);
            buffer.Append("; DependencyCheck = ").Append(DependencyCheck);
            buffer.Append("; InitMethodName = ").Append(InitMethodName);
            buffer.Append("; DestroyMethodName = ").Append(DestroyMethodName);
            buffer.Append("; FactoryMethodName = ").Append(FactoryMethodName);
            buffer.Append("; FactoryObjectName = ").Append(FactoryObjectName);
            if (StringUtils.HasText(ResourceDescription))
            {
                buffer.Append("; defined in = ").Append(ResourceDescription);
            }
            return buffer.ToString();
        }

        #endregion

        #region Fields

        private ConstructorArgumentValues constructorArgumentValues = new ConstructorArgumentValues();
        private MutablePropertyValues propertyValues = new MutablePropertyValues();
        private EventValues eventHandlerValues = new EventValues();
        private MethodOverrides methodOverrides = new MethodOverrides();
        private string resourceDescription = null;
        private bool isSingleton = true;
        private bool isPrototype = false;
        private bool isLazyInit = false;
        private bool isAbstract = false;
        private string scope = SCOPE_SINGLETON;
        private ObjectRole role = ObjectRole.ROLE_APPLICATION;
        private object objectType;
        private AutoWiringMode autowireMode = AutoWiringMode.No;
        private DependencyCheckingMode dependencyCheck = DependencyCheckingMode.None;
        private string[] dependsOn;
        private bool autowireCandidate = true;
        private string initMethodName = null;
        private string destroyMethodName = null;
        private string factoryMethodName = null;
        private string factoryObjectName = null;

        #endregion
    }
}