Example #1
0
        private BlockExpression GenerateListPropertyBlock()
        {
            var listInit = InitializeListIfNull(Target, mapping);

            var itemGenerator = new XmlSerializerGenerator(mapping.PropertyCache.Property.PropertyType.GetGenericArguments()[0], null, false);

            var makeItem = Expression.Invoke(                                                         //ReadSensor()
                itemGenerator.MakeReadElement(parentProperty: mapping.PropertyCache),
                itemGenerator.GetInnerReadElementParameters(generator.update, true)
                );

            //Assign the result of makeitem to a local variable before adding to the list
            //to prevent a million local variables being created.
            var temp   = Expression.Variable(makeItem.Type, "temp");
            var assign = Expression.Assign(temp, makeItem);
            var add    = XmlExpressionConstants.ListAdd(listInit.Item1, temp);

            var block = Expression.Block(
                typeof(void),
                new ParameterExpression[] { temp },
                new Expression[] { assign, add }
                );

            return(block);
        }
        /// <summary>
        /// Construct an expression like
        ///
        /// var obj = new Obj();
        ///
        /// while(ReadAttribute())
        /// {
        ///     ...
        /// }
        ///
        /// while(ReadElement())
        /// {
        ///     ...
        /// }
        ///
        /// return obj;
        /// </summary>
        /// <param name="first">Whether this is the outer object being deserialized.</param>
        /// <param name="parentProperty">The property on our parent object this object will be deserialized to.</param>
        /// <returns></returns>
        internal Expression MakeReadElement(bool first = false, PropertyCache parentProperty = null)
        {
            Expression          moveToContent = null;
            ParameterExpression itemPointer   = Expression.Variable(typeof(object), "item");

            if (first)
            {
                moveToContent = XmlExpressionConstants.XmlReader_MoveToContent;
            }

            var makeNew = Expression.Assign(Target, Expression.New(trueType));             //obj = new TableData<Sensor>();

            var initArrays = InitializeArrays();                                           //if (obj.Items == null) obj.Items = new List<Sensor>();

            var newFlags = Expression.NewArrayBounds(                                      //new bool[40]
                typeof(bool),
                Expression.Constant(Mappings.Count)
                );
            var flagsAssignment = XmlExpressionConstants.SerializerFlags.Assign(newFlags); //var flagsArray = new bool[40]

            var newName = Expression.NewArrayBounds(typeof(object),                        //new object[42]
                                                    Expression.Constant(Mappings.Sum(m => m.AttributeValue.Length))
                                                    );
            var nameAssignment = XmlExpressionConstants.SerializerNames.Assign(newName);   //var nameArray = new object[42]

            var populateNameTable = PopulateNameTable(parentProperty);                     //InitTableData(nameArray)

            var processAttributes    = ProcessAttributes();
            var skipOrProcessElement = SkipOrProcessElement();

            var blockExpressions = new List <Expression>();

            if (first)
            {
                blockExpressions.Add(moveToContent);                                       //reader.MoveToContent();
            }
            if (!update)
            {
                blockExpressions.Add(makeNew);                                             //var obj = new TObj()
            }
            else
            {
                var nameTable = XmlExpressionConstants.XmlReader_NameTable;
                var add       = XmlExpressionConstants.ListAdd(nameTable, Expression.Constant("item"));

                blockExpressions.Add(itemPointer.Assign(add));
                blockExpressions.Add(XmlExpressionConstants.XmlReader_ReadToFollowing(Expression.Convert(itemPointer, typeof(string))));
            }

            if (initArrays.Count > 0)
            {
                blockExpressions.AddRange(initArrays);                                     //obj.Items = new List<Sensor>();
            }
            blockExpressions.Add(flagsAssignment);                                         //var flagsArray = new bool[40]
            blockExpressions.Add(nameAssignment);                                          //var nameArray = new object[42]

            if (populateNameTable != null)
            {
                blockExpressions.Add(populateNameTable);                                   //InitTableData(nameArray)
            }
            blockExpressions.Add(processAttributes);                                       //if (!flagsArray[0] && (object)reader.Name == nameArray[0])
            blockExpressions.Add(XmlExpressionConstants.XmlReader_MoveToContent);
            blockExpressions.Add(skipOrProcessElement);

            var variables = new List <ParameterExpression>();

            if (!update)
            {
                variables.Add(Target);                                                     //TableData<Sensor> obj;
            }
            variables.Add(XmlExpressionConstants.SerializerFlags);                         //bool[] flagArray;
            variables.Add(XmlExpressionConstants.SerializerNames);                         //object[] nameArray;

            if (update)
            {
                variables.Add(itemPointer);
            }

            var block = Expression.Block(
                variables.ToArray(),
                blockExpressions
                );

            var lambda = Expression.Lambda(
                block,
                $"Read{GetDynamicTypeNameInternal(trueType)}",
                GetReadElementParameters(null, false).Cast <ParameterExpression>().ToArray()
                );

            return(LambdaOrDelegate(lambda));
        }