private ObjectDefinition GetObjectDefinition(XmlElement rootElement, XmlElement element, string id)
        {
            ObjectDefinition objectDefinition = new ObjectDefinition();

            // Read the id
            if (element.HasAttribute("id"))
            {
                objectDefinition.Id = element.GetAttribute("id");
            }
            else
            {
                throw new ConfigurationErrorsException("The id attribute is required for all configured object elements.");
            }

            // Read the type
            if (element.HasAttribute("type"))
            {
                objectDefinition.Type = Type.GetType(element.GetAttribute("type"), true);
            }
            else
            {
                throw new ConfigurationErrorsException("The typeName attribute is required for all configured object elements.");
            }

            // Read the singleton flag
            if (element.HasAttribute("singleton"))
            {
                if (element.GetAttribute("singleton") == "true")
                {
                    objectDefinition.IsSingleton = true;
                }
            }

            if (element.HasChildNodes)
            {
                // Read the constructor information
                XmlElement constructorElement = (XmlElement) element.SelectSingleNode("constructor");
                if (constructorElement != null && constructorElement.HasChildNodes)
                {
                    foreach (XmlElement parameterElement in constructorElement.SelectNodes("parameter"))
                    {
                        object parameterValue;

                        // Is the parameter a reference to another object?
                        if (parameterElement.HasAttribute("reference"))
                        {
                            if (objectDefinitions.ContainsKey(parameterElement.GetAttribute("reference")))
                            {
                                parameterValue = objectDefinitions[parameterElement.GetAttribute("reference")];
                            }
                            else
                            {
                                string referenceId = parameterElement.GetAttribute("reference");
                                XmlElement referenceElement = (XmlElement) rootElement.SelectSingleNode("object[@id = '" + referenceId + "']");
                                ObjectDefinition referenceDefinition = GetObjectDefinition(rootElement, referenceElement, referenceId);
                                objectDefinitions.Add(referenceDefinition.Id, referenceDefinition);

                                parameterValue = referenceDefinition;
                            }
                        }
                        else
                        {
                            if (parameterElement.HasAttribute("value"))
                            {
                                parameterValue = parameterElement.GetAttribute("value");
                            }
                            else
                            {
                                throw new ConfigurationErrorsException("The value attribute is required for all configured constructor arguments.");
                            }
                        }

                        objectDefinition.ConstructorParameters.Add(parameterValue);
                    }
                }

                // Read the property information
                foreach (XmlElement propertyElement in element.SelectNodes("property"))
                {
                    string propertyName;
                    if (propertyElement.HasAttribute("name"))
                    {
                        propertyName = propertyElement.GetAttribute("name");
                    }
                    else
                    {
                        throw new ConfigurationErrorsException("The name attribute is required for all configured properties.");
                    }

                    // Is the parameter a reference to another object?
                    object propertyValue;
                    if (propertyElement.HasAttribute("reference"))
                    {
                        if (objectDefinitions.ContainsKey(propertyElement.GetAttribute("reference")))
                        {
                            propertyValue = objectDefinitions[propertyElement.GetAttribute("reference")];
                        }
                        else
                        {
                            string referenceId = propertyElement.GetAttribute("reference");
                            XmlElement referenceElement = (XmlElement) rootElement.SelectSingleNode("object[@id = '" + referenceId + "']");
                            ObjectDefinition referenceDefinition = GetObjectDefinition(rootElement, referenceElement, referenceId);
                            objectDefinitions.Add(referenceDefinition.Id, referenceDefinition);

                            propertyValue = referenceDefinition;
                        }
                    }
                    else
                    {
                        if (propertyElement.HasAttribute("value"))
                        {
                            propertyValue = propertyElement.GetAttribute("value");
                        }
                        else
                        {
                            throw new ConfigurationErrorsException("The value attribute is required for all configured properties.");
                        }
                    }

                    objectDefinition.Properties.Add(propertyName, propertyValue);
                }
            }

            return objectDefinition;
        }
        /// <summary>
        /// Creates an object instance based on the specified object definition.
        /// </summary>
        /// <param name="objectDefinition">The definition of the object to create.</param>
        /// <returns>An instance based on the specified object definition.</returns>
        private static object GetObject(ObjectDefinition objectDefinition)
        {
            object instance = null;
            FormatterConverter formatterConverter = new FormatterConverter();

            if (objectDefinition.ConstructorParameters.Count > 0)
            {
                ConstructorInfo[] constructors = objectDefinition.Type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                foreach (ConstructorInfo constructorInfo in constructors)
                {
                    ParameterInfo[] constructorParameters = constructorInfo.GetParameters();
                    if (constructorParameters.Length == objectDefinition.ConstructorParameters.Count)
                    {
                        bool match = true;
                        for (int i = 0; i < constructorParameters.Length; i++)
                        {
                            if (objectDefinition.ConstructorParameters[i] is ObjectDefinition)
                            {
                                ObjectDefinition constructorParameterDefinition = (ObjectDefinition) objectDefinition.ConstructorParameters[i];
                                if (constructorParameters[i].ParameterType != constructorParameterDefinition.Type)
                                {
                                    match = false;
                                    break;
                                }
                            }
                            else if (constructorParameters[i].ParameterType != objectDefinition.ConstructorParameters[i].GetType())
                            {
                                match = false;
                                break;
                            }
                        }

                        if (match)
                        {
                            List<object> parameters = new List<object>();
                            for (int i = 0; i < objectDefinition.ConstructorParameters.Count; i++)
                            {
                                object parameter = objectDefinition.ConstructorParameters[i];
                                if (parameter is ObjectDefinition)
                                {
                                    ObjectDefinition parameterDefinition = (ObjectDefinition) parameter;
                                    parameters.Add(GetObject(parameterDefinition));
                                }
                                else
                                {
                                    parameter = formatterConverter.Convert(parameter, constructorParameters[i].ParameterType);
                                    parameters.Add(parameter);
                                }
                            }

                            instance = constructorInfo.Invoke(parameters.ToArray());
                            break;
                        }
                    }
                }
            }
            else
            {
                instance = Activator.CreateInstance(objectDefinition.Type);
            }

            if (instance == null)
            {
                throw new ArgumentException("A match could not be found for the specified ObjectDefinition [" + objectDefinition.Id + "].  Please verify the class definition and the configured constructor information.");
            }
            else
            {
                if (objectDefinition.Properties.Count > 0)
                {
                    foreach (PropertyInfo propertyInfo in objectDefinition.Type.GetProperties())
                    {
                        object propertyValue = objectDefinition.Properties[propertyInfo.Name];
                        if (propertyValue != null)
                        {
                            if (propertyValue is ObjectDefinition)
                            {
                                propertyValue = GetObject(propertyValue as ObjectDefinition);
                            }
                            propertyInfo.SetValue(instance, formatterConverter.Convert(propertyValue, propertyInfo.PropertyType), null);
                        }
                    }
                }

                return instance;
            }
        }