/// <summary>
 /// Saves the ObjectDefinition instance using the specific key.
 /// </summary>
 /// <param name="key">The specific key to use</param>
 /// <param name="definition">The ObjectDefinition instance to save</param>
 /// <exception cref="ObjectSourceException">
 /// Wraps any implementation specific exceptions that may occur while saving the definition
 /// info but may also indicate incomplete definition info (missing type name), parsing errors
 /// if the source uses string representations or some other implementation specific error.
 /// </exception>
 /// <exception cref="ArgumentNullException">If the key is null or definition is null.</exception>
 /// <exception cref="ArgumentException">If the key is empty.</exception>
 public abstract void SaveDefinition(string key, ObjectDefinition definition);
        /// <summary>
        /// <para>
        /// Saves the given object definition in NESTED hierarchical structure.
        /// </para>
        /// </summary>
        ///
        /// <param name="key">
        /// The key of the object definition.
        /// </param>
        /// <param name="definition">
        /// The object definition to be saved.
        /// </param>
        private void SaveNestedObjectDefinition(string key, ObjectDefinition definition)
        {
            // The root config of the definition
            IConfiguration objectConfig = AddRootConfig(ConfigObject, key);

            // Write all simple attributes of the definition
            AddNewNestedConfig(objectConfig, ConfigAppDomain, definition.AppDomain);
            AddNewNestedConfig(objectConfig, ConfigAssembly, definition.Assembly);
            AddNewNestedConfig(objectConfig, ConfigTypeName, definition.TypeName);
            AddNewNestedConfig(objectConfig, ConfigIgnoreCase, definition.IgnoreCase);
            AddNewNestedConfig(objectConfig, ConfigInstantiationLifetime, definition.InstantiationLifetime);
            AddNewNestedConfig(objectConfig, ConfigMethodName, definition.MethodName);

            // Get the method call definitions
            MethodCallDefinition[] methods = definition.MethodCalls;
            if (methods.Length > 0)
            {
                // The methods config
                IConfiguration methodsConfig = new DefaultConfiguration(ConfigMethods);

                // Write each method call definition
                int index = 0;
                foreach (MethodCallDefinition method in methods)
                {
                    SaveNestedMethodDefinition(methodsConfig, ConfigMethod + (++index), method);
                }

                // Add the methods config into root config
                objectConfig.AddChild(AbstractConfiguration.Synchronized(methodsConfig));
            }

            if (definition.ParamTypes.Length > 0)
            {
                // Write the parameter definitions of the object
                SaveNestedParameters(objectConfig, definition.ParamTypes, definition.ParamValues);
            }
        }
        /// <summary>
        /// <para>
        /// Saves the specified object definition in <see cref="IConfiguration"/>
        /// object with the specified key.
        /// </para>
        /// </summary>
        ///
        /// <remarks>
        /// <para>
        /// If an object with the same key already exists, the old definition will be overwritten.
        /// </para>
        ///
        /// <para>
        /// The structure used to save the definition depends on <see cref="ConfigurationType"/>.
        /// </para>
        /// </remarks>
        ///
        /// <param name="key">
        /// The key to use. Can't be null or empty.
        /// </param>
        /// <param name="definition">
        /// The definition to be saved.
        /// </param>
        ///
        /// <returns>
        /// The object definition info.
        /// </returns>
        ///
        /// <exception cref="ArgumentNullException">
        /// If the key or definition is null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// If the key is an empty string.
        /// </exception>
        public override void SaveDefinition(string key, ObjectDefinition definition)
        {
            ValidateNotNullOrEmpty(key, "key");
            ValidateNotNull(definition, "definition");

            // Try to remove the object definition first
            DeleteDefinition(key);

            if (configurationType == ConfigurationType.Flat)
            {
                SaveFlatObjectDefinition(key, definition);
            }
            else
            {
                SaveNestedObjectDefinition(key, definition);
            }
        }
        /// <summary>
        /// <para>
        /// Saves the object definition into FLAT structure.
        /// </para>
        /// </summary>
        ///
        /// <param name="nameSpace">
        /// The namespace of the configuration.
        /// </param>
        /// <param name="definition">
        /// The object definition to be saved.
        /// </param>
        private void SaveFlatObjectDefinition(string nameSpace, ObjectDefinition definition)
        {
            IConfiguration objectConfig = AddRootConfig(ConfigNamespace, nameSpace);
            int propertyIndex = 0;

            // Save simple attributes into "property" nodes
            AddNewFlatConfig(objectConfig, ++propertyIndex, ConfigAppDomain, definition.AppDomain);
            AddNewFlatConfig(objectConfig, ++propertyIndex, ConfigAssembly, definition.Assembly);
            AddNewFlatConfig(objectConfig, ++propertyIndex, ConfigTypeName, definition.TypeName);
            AddNewFlatConfig(objectConfig, ++propertyIndex, ConfigIgnoreCase, definition.IgnoreCase);
            AddNewFlatConfig(objectConfig, ++propertyIndex,
                ConfigInstantiationLifetime, definition.InstantiationLifetime);
            AddNewFlatConfig(objectConfig, ++propertyIndex, ConfigMethodName, definition.MethodName);

            MethodCallDefinition[] methods = definition.MethodCalls;
            if (methods.Length > 0)
            {
                // The method name list
                object[] methodNames = new string[methods.Length];
                for (int i = 0; i < methodNames.Length; ++i)
                {
                    // Write method definitions
                    methodNames[i] = methods[i].MethodName;
                    SaveFlatMethodDefinition(nameSpace + "." + methods[i].MethodName, methods[i]);
                }

                AddNewFlatConfig(objectConfig, ++propertyIndex, ConfigMethods, methodNames);
            }

            if (definition.ParamTypes.Length > 0)
            {
                // Write parameter definitions
                SaveFlatParameters(
                    nameSpace + "." + ConfigParameters, definition.ParamTypes, definition.ParamValues);
            }
        }