private Expression ProcessAttributes()
        {
            var builder = new LadderBuilder(this, XmlAttributeType.Attribute);
            var processAttributesBody = builder.GetLadder();

            var @break = Expression.Label("break");

            var condition = Expression.IfThenElse(
                XmlExpressionConstants.XmlReader_MoveToNextAttribute,
                processAttributesBody,
                Expression.Break(@break)
                );

            var loop = Expression.Loop(condition, @break);

            return(loop);
        }
        private Expression ProcessElement()
        {
            var nodeType   = XmlExpressionConstants.XmlReader_NodeType;
            var element    = Expression.Constant(XmlNodeType.Element);
            var endElement = Expression.Constant(XmlNodeType.EndElement);
            var none       = Expression.Constant(XmlNodeType.None);

            var loopCondition = Expression.AndAlso(
                nodeType.NotEqual(endElement), //reader.NodeType != XmlNodeType.EndElement
                nodeType.NotEqual(none)        //reader.NodeType != XmlNodeType.none
                );

            var builder = new LadderBuilder(this, XmlAttributeType.Element);

            var isElement     = nodeType.Equal(element);
            var elementLadder = builder.GetLadder();
            var skipUnknown   = XmlExpressionConstants.Serializer_SkipUnknownNode;

            Expression loopBody;

            var textMappings = Mappings.Where(m => m.AttributeType == XmlAttributeType.Text).ToList();

            if (textMappings.Count > 0)
            {
                if (textMappings.Count > 1)
                {
                    var str = string.Join(", ", textMappings.Select(m => m.PropertyCache.Property.Name));

                    throw new InvalidOperationException($"Canot deserialize type {trueType.Name} as multiple properties contain a {nameof(XmlTextAttribute)} ({str})."); //todo: complain about the name of this type and the properties that have the two xmltextattributes
                }

                var isText    = nodeType.Equal(Expression.Constant(XmlNodeType.Text));
                var textBlock = GetTextBlock(textMappings.Single());

                loopBody = new ElseIfExpression(
                    new[]
                {
                    Expression.IfThen(isElement, elementLadder),     //if (reader.NodeType == XmlNodeType.Element) [Ladder]
                    Expression.IfThen(isText, textBlock)             //else if (reader.NodeType == XmlNodeType.Text) [TextBlock]
                },
                    skipUnknown                                      //else SkipUnknownNode()
                    );
            }
            else
            {
                loopBody = Expression.IfThenElse(                    //if (reader.NodeType == XmlNodeType.Element)
                    isElement,                                       //    [Ladder]
                    elementLadder,                                   //else
                    skipUnknown                                      //    SkipUnknownNode()
                    );
            }

            var @break = Expression.Label("break");

            var loop = Expression.Loop(
                Expression.IfThenElse(loopCondition, loopBody, Expression.Break(@break)),
                @break
                );

            var body = new List <Expression>();

            body.Add(XmlExpressionConstants.XmlReader_ReadStartElement);
            body.Add(XmlExpressionConstants.XmlReader_MoveToContent);
            body.Add(loop);
            body.Add(XmlExpressionConstants.XmlReader_ReadEndElement);

            var validator = MakeValidateValueTypes();

            if (validator != null)
            {
                body.Add(validator);
            }

            if (!update)
            {
                body.Add(Target);
            }

            return(Expression.Block(body.ToArray()));
        }