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