Ejemplo n.º 1
0
        /// <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&lt;&gt;.</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);
        }
Ejemplo n.º 2
0
        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;
                }
            }
        }
Ejemplo n.º 3
0
        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);
        }
Ejemplo n.º 4
0
        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);
                    }
                }
            }
        }
Ejemplo n.º 5
0
        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);
        }