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; } }