/// <summary> /// Creates and populates a new instance of the generic type given in the supplied GenericTypeElementDefinition, /// using the supplied XML element as the source. /// </summary> /// <param name="genericTypeDefinition">The definition of the generic type to be created.</param> /// <param name="sourceElement">The source XML element for this object.</param> /// <param name="parentObject">The parent object of this object.</param> /// <returns>A new instance of the required type, typically of the form SomeType<>.</returns> /// <remarks>The inner type of the target type is specified via an attribute on the supplied input XML element.</remarks> /// <exception cref="MissingMandatoryValueException">Thrown when...<ul> /// <li></li> /// </ul></exception> private object CreateObject(GenericTypeElementDefinition genericTypeDefinition, XElement sourceElement, object parentObject) { _log.DebugFormat("CreateObject(GenericTypeElementDefinition, XElement) called; ElementName='{0}'.", genericTypeDefinition.ElementName); object[] constructorParameterValues; Type[] constructorParameterTypes; GetConstructorParameters(genericTypeDefinition, sourceElement, parentObject, out constructorParameterTypes, out constructorParameterValues); string innerTypeName = ReadAttribute(sourceElement.Attributes(), genericTypeDefinition.AttributeForInnerType, typeof(string)) as string; if (string.IsNullOrEmpty(innerTypeName)) { throw ThrowHelper.New <MissingMandatoryValueException>(this, new ExceptionInfo(sourceElement), ErrorMessages.MissingMandatoryAttribute, genericTypeDefinition.AttributeForInnerType.LocalName, genericTypeDefinition.ElementName.LocalName); } Type innerType; if (string.IsNullOrEmpty(genericTypeDefinition.InnerTypeNamespace)) { innerType = Type.GetType(innerTypeName); } else { innerType = Type.GetType(string.Format("{0}.{1}", genericTypeDefinition.InnerTypeNamespace, innerTypeName)); } if (innerType == null) { throw ThrowHelper.New <InvalidFieldValueException>(this, new ExceptionInfo(sourceElement), ErrorMessages.UnrecognisedTypeError, innerTypeName, genericTypeDefinition.AttributeForInnerType.LocalName, genericTypeDefinition.ElementName.LocalName); } object newObject = CreateRawObject(genericTypeDefinition.TargetType, new Type[] { innerType }, constructorParameterTypes, constructorParameterValues); IEnumerable <XAttribute> attributes = sourceElement.Attributes(); try { ProcessAttributes(newObject.GetType(), genericTypeDefinition.Attributes, attributes, newObject); ProcessAttributes(newObject.GetType(), genericTypeDefinition.InnerTypeToAttributesMap[innerType], attributes, newObject); } catch (MissingMandatoryValueException ex) { throw ThrowHelper.Rethrow(this, ex, new ExceptionInfo(sourceElement), ErrorMessages.GeneralElementProcessingError, string.Empty); } ProcessChildren(genericTypeDefinition, sourceElement, newObject); if (newObject.GetType() == _notifyCreationOfType) { NotifyClassDeserialized(_notifyCreationOfType, newObject); } return(newObject); }
private void ProcessChildProperty(ChildElementDefinition childDefinition, PropertyInfo property, Type targetType, object target, object childObject) { _log.DebugFormat("ProcessChildProperty called; ElementName='{0}', Property={1}.", childDefinition.ElementDefinition.ElementName, property.Name); string containerMethod; if (childDefinition.ContainerMethod is StandardContainerMethod) { StandardContainerMethod method = (StandardContainerMethod)childDefinition.ContainerMethod; if (method == StandardContainerMethod.Assign) { SetPropertyValue(property, target, childObject); return; } else { containerMethod = Enum.GetName(typeof(StandardContainerMethod), childDefinition.ContainerMethod); } } else { containerMethod = childDefinition.ContainerMethod as string; } MethodInfo targetMethod = property.PropertyType.GetMethod(containerMethod, new Type[] { targetType }); if (targetMethod == null) { throw ThrowHelper.New <InternalErrorException>(this, InternalErrors.ContainerMethodNotFoundOnObject, containerMethod, targetType.FullName); } try { targetMethod.Invoke(property.GetValue(target, null), new object[] { childObject }); } catch (TargetInvocationException ex) { if (ex.InnerException != null) { throw ThrowHelper.Rethrow(this, ex.InnerException, ErrorMessages.UnableToInvokeMethodError, string.Format("the {0} method on the {1} property", containerMethod, property.Name)); } else { throw; } } }
private object CreateObject(ElementDefinition definition, XElement sourceElement, object parentObject) { _log.DebugFormat("CreateObject(ElementDefinition, XElement) called; ElementName='{0}.'", definition.ElementName); Type[] constructorParameterTypes; object[] constructorParameterValues; GetConstructorParameters(definition, sourceElement, parentObject, out constructorParameterTypes, out constructorParameterValues); object newObject = CreateRawObject(definition.TargetType, constructorParameterTypes, constructorParameterValues); if (definition.CacheElementValueInstruction != null) { _elementValueCache[definition.CacheElementValueInstruction.CacheKey] = newObject; } IEnumerable <XAttribute> attributes = sourceElement.Attributes(); try { ProcessAttributes(definition.TargetType, definition.Attributes, attributes, newObject); } catch (Atdl4netException ex) { throw ThrowHelper.Rethrow(this, ex, new ExceptionInfo(sourceElement), ErrorMessages.GeneralElementProcessingError, string.Empty); } ProcessChildren(definition, sourceElement, newObject); if (newObject.GetType() == _notifyCreationOfType) { NotifyClassDeserialized(_notifyCreationOfType, newObject); } return(newObject); }
private void ProcessChildren(ElementDefinition definition, XElement sourceElement, object target) { _log.DebugFormat("ProcessChildren called; ElementName='{0}'", definition.ElementName); // We have to reflect the target type as we can't rely on the Definition to contain it (e.g. MultiTypeElementDefinition). Type targetType = target.GetType(); foreach (ChildElementDefinition childDefinition in definition.ChildElements) { bool isRecursiveDefinition = childDefinition.ElementDefinition is RecursiveTypeElementDefinition; bool hasContainerElement = !isRecursiveDefinition && childDefinition.ContainerElementName != null; IEnumerable <XElement> matchingChildElements; ElementDefinition targetDefinition = isRecursiveDefinition ? definition : childDefinition.ElementDefinition; if (hasContainerElement) { XElement containerElement = (from e in sourceElement.Elements(childDefinition.ContainerElementName) select e).FirstOrDefault(); if (containerElement == null) { return; } matchingChildElements = from e in containerElement.Elements(childDefinition.ElementDefinition.ElementName) select e; } else { matchingChildElements = from e in sourceElement.Elements(targetDefinition.ElementName) select e; } foreach (XElement childElement in matchingChildElements) { object childObject; if (targetDefinition is GenericTypeElementDefinition) { childObject = CreateObject(targetDefinition as GenericTypeElementDefinition, childElement, target); } else if (targetDefinition is MultiTypeElementDefinition) { childObject = CreateObject(targetDefinition as MultiTypeElementDefinition, childElement, target); } else { childObject = CreateObject(targetDefinition, childElement, target); } PropertyInfo property = targetType.GetProperty(childDefinition.ContainerProperty); if (property == null) { throw ThrowHelper.New <InternalErrorException>(this, InternalErrors.PropertyNotFoundOnObjectInternal, childDefinition.ContainerProperty, targetType.FullName); } try { // For the case of MultiTypeElementDefinition we must use the reflected type ProcessChildProperty(childDefinition, property, targetDefinition.TargetType ?? childObject.GetType(), target, childObject); } catch (Atdl4netException ex) { throw ThrowHelper.Rethrow(this, ex, new ExceptionInfo(childElement), ErrorMessages.GeneralElementProcessingError, definition.ElementName.LocalName); } catch (ArgumentException ex) { throw ThrowHelper.New <Atdl4netException>(this, ex, new ExceptionInfo(childElement), ErrorMessages.GeneralElementProcessingError, definition.ElementName.LocalName, ex.Message); } } } }
private object CreateObject(MultiTypeElementDefinition multiTypeDefinition, XElement sourceElement, object parentObject) { _log.DebugFormat("CreateObject(MultiTypeElementDefinition, XElement) called; ElementName='{0}'.", multiTypeDefinition.ElementName); object[] constructorParameterValues; Type[] constructorParameterTypes; GetConstructorParameters(multiTypeDefinition, sourceElement, parentObject, out constructorParameterTypes, out constructorParameterValues); string typeName = ReadAttribute(sourceElement.Attributes(), multiTypeDefinition.AttributeForType, typeof(string)) as string; if (string.IsNullOrEmpty(typeName)) { throw ThrowHelper.New <MissingMandatoryValueException>(this, new ExceptionInfo(sourceElement), ErrorMessages.MissingMandatoryAttribute, multiTypeDefinition.AttributeForType.LocalName, multiTypeDefinition.ElementName.LocalName); } // If the value for the typename is in an XML namespace, remove it. if (typeName.Contains(':') && typeName.IndexOf(':') < typeName.Length - 1) { typeName = typeName.Substring(typeName.IndexOf(':') + 1); } Type targetType; if (string.IsNullOrEmpty(multiTypeDefinition.TypeNamespace)) { targetType = Type.GetType(typeName); } else { targetType = Type.GetType(string.Format("{0}.{1}", multiTypeDefinition.TypeNamespace, typeName)); } if (targetType == null) { throw ThrowHelper.New <InvalidFieldValueException>(this, new ExceptionInfo(sourceElement), ErrorMessages.UnrecognisedTypeError, typeName, multiTypeDefinition.AttributeForType.LocalName, multiTypeDefinition.ElementName.LocalName); } object newObject = CreateRawObject(targetType, constructorParameterTypes, constructorParameterValues); IEnumerable <XAttribute> attributes = sourceElement.Attributes(); try { ProcessAttributes(newObject.GetType(), multiTypeDefinition.Attributes, attributes, newObject); ProcessAttributes(newObject.GetType(), multiTypeDefinition.TypeToAttributesMap[targetType], attributes, newObject); } catch (Atdl4netException ex) { throw ThrowHelper.Rethrow(this, ex, new ExceptionInfo(sourceElement), ErrorMessages.GeneralElementProcessingError, string.Empty); } ProcessChildren(multiTypeDefinition, sourceElement, newObject); if (newObject.GetType() == _notifyCreationOfType) { NotifyClassDeserialized(_notifyCreationOfType, newObject); } return(newObject); }