/// <summary> /// Construct an expression like /// /// if (reader.NodeType == XmlNodeType.Element /// { /// return ProcessTableDataInternal(); /// } /// else /// { /// SkipUnknownNode(); /// return null; /// } /// </summary> /// <param name="delegateType">The type of object that will be returned by the delegate.</param> /// <param name="trueType">The type of object the delegate will actually manipulate. If this object is null, <paramref name="delegateType"/> is used.</param> /// <param name="update">Whether this delegate will be used for constructing a new object or updating an existing one.</param> /// <returns></returns> internal static LambdaExpression MakeLambda(Type delegateType, Type trueType, bool update = false) { if (trueType == null) { trueType = delegateType; } if (trueType == typeof(ObjectProperty) || trueType == typeof(ObjectPropertyInternal)) { //A single ObjectProperty doesn't actually bother with XML; it simply skips straight //to deserializing the value return(MakeObjectPropertyLambda(trueType)); } var generator = new XmlSerializerGenerator(delegateType, trueType, update); var processInternal = generator.MakeReadElement(true, null); //ReadTableData var invokeInternal = Expression.Invoke( //ReadTableData(serializer, reader, validateValueTypes); processInternal, generator.GetReadElementParameters(Expression.Convert(generator.DelegateTarget, trueType), true) ); var moveToContent = XmlExpressionConstants.XmlReader_MoveToContent; //reader.MoveToContent(); //Construct the test of the if statement var nodeType = XmlExpressionConstants.XmlReader_NodeType; //reader.NodeType var element = Expression.Constant(XmlNodeType.Element); //XmlNodeType.Element var equal = Expression.Equal(nodeType, element); //reader.NodeType == XmlNodeType.Element var list = new List <Expression>(); list.Add(XmlExpressionConstants.Serializer_SkipUnknownNode); //reader.SkipUnknownNode(); if (!update) { list.Add(Expression.Constant(null, delegateType)); //return null; } //Construct the ifFalse block of the if statement var skipBlock = Expression.Block( //{ update ? typeof(void) : delegateType, // reader.SkipUnknownNode(); list.ToArray() // return null; } ); //Construct the if statement var ifElement = Expression.Condition( //if (reader.NodeType == XmlNodeType.Element) equal, // ReadTableData(); Expression.Block(invokeInternal), //else { skipBlock // reader.SkipUnknownNode(); ); // return null; } //Construct the entry point to the deserializer, ReadTableDataOuter return(Expression.Lambda( //TableData<Sensor> ReadTableDataOuter() { Expression.Block( // reader.MoveToContent(); moveToContent, // if (reader.NodeType == XmlNodeType.Element) ifElement // reader.ReadTableData(); ), // else { $"Read{GetDynamicTypeNameInternal(trueType)}Outer", // reader.SkipUnknownNode(); generator.GetReadElementParameters(generator.DelegateTarget, false, false).Cast <ParameterExpression>().ToArray() //return null; } )); //} }
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); }
public Expression Deserialize() { if (PropertyType == typeof(string)) { return(ValueOrConverted(XmlExpressionConstants.ToNullableString(readStr))); } else if (PropertyType == typeof(int)) { return(GetValue(XmlExpressionConstants.ToInt32, false)); } else if (PropertyType == typeof(double)) { return(GetValue(XmlExpressionConstants.ToDouble, false)); } else if (PropertyType == typeof(bool)) { return(GetValue(XmlExpressionConstants.ToBool, false)); } else if (PropertyType == typeof(DateTime)) { return(GetValue(XmlExpressionConstants.ToDateTime, false, XmlExpressionConstants.ToDouble, XmlExpressionConstants.ToDateTimeFromDouble)); } else if (PropertyType == typeof(TimeSpan)) { return(GetValue(XmlExpressionConstants.ToTimeSpan, false, XmlExpressionConstants.ToInt32, XmlExpressionConstants.ToTimeSpanFromInt32)); } else if (PropertyType == typeof(string[])) { var attrib = mapping.PropertyCache.GetAttribute <SplittableStringAttribute>(); if (attrib != null) { return(ValueOrConverted(XmlExpressionConstants.ToSplittableStringArray(readStr, Expression.Constant(attrib.Character)))); } else { throw new NotImplementedException(); } } else if (PropertyType.IsEnum) { return(ValueOrConverted(GetEnumSwitch(readStr, PropertyType))); } else if (PropertyType == typeof(int?)) { return(GetValue(XmlExpressionConstants.ToInt32, true)); } else if (PropertyType == typeof(double?)) { return(GetValue(XmlExpressionConstants.ToDouble, true)); } else if (PropertyType == typeof(bool?)) { return(GetValue(XmlExpressionConstants.ToBool, true)); } else if (PropertyType == typeof(DateTime?)) { return(GetValue(XmlExpressionConstants.ToNullableDateTimeSkipCheck, true, XmlExpressionConstants.ToDouble, XmlExpressionConstants.ToDateTimeFromDouble)); } else if (PropertyType == typeof(TimeSpan?)) { return(GetValue(XmlExpressionConstants.ToTimeSpan, true, XmlExpressionConstants.ToInt32, XmlExpressionConstants.ToTimeSpanFromInt32)); } else { var underlying = Nullable.GetUnderlyingType(PropertyType); if (underlying != null && underlying.IsEnum) { return(GetNullableEnumSwitch(underlying, PropertyType)); } } if (PropertyType.GetTypeCache().GetAttribute <XmlRootAttribute>() != null) { var customTypeGenerator = new XmlSerializerGenerator(PropertyType, null, false); var customTypeLambda = customTypeGenerator.MakeReadElement(); return(Expression.Invoke(customTypeLambda, customTypeGenerator.GetInnerReadElementParameters(generator?.update ?? false, true))); } return(null); }
public Expression Deserialize(ref Expression initExpression, ref List <ParameterExpression> variables) { if (PropertyType == typeof(string)) { return(ValueOrConverted(XmlExpressionConstants.ToNullableString(readStr))); } else if (PropertyType == typeof(int)) { return(GetValue(XmlExpressionConstants.ToInt32, false)); } else if (PropertyType == typeof(double)) { return(GetValue(XmlExpressionConstants.ToDouble, false)); } else if (PropertyType == typeof(bool)) { return(GetValue(XmlExpressionConstants.ToBool, false)); } else if (PropertyType == typeof(DateTime)) { return(GetValue(XmlExpressionConstants.ToDateTime, false, XmlExpressionConstants.ToDouble, XmlExpressionConstants.ToDateTimeFromDouble)); } else if (PropertyType == typeof(TimeSpan)) { return(GetValue(XmlExpressionConstants.ToTimeSpan, false, XmlExpressionConstants.ToInt32, XmlExpressionConstants.ToTimeSpanFromInt32)); } else if (PropertyType == typeof(string[])) { var attrib = mapping.PropertyCache.GetAttribute <SplittableStringAttribute>(true); if (attrib != null) { var charsVariable = Expression.Variable(typeof(char[]), "splitChars"); var arrayInit = Expression.NewArrayInit(typeof(char), attrib.Characters.Select(c => Expression.Constant(c))); initExpression = Expression.Assign(charsVariable, arrayInit); variables.Add(charsVariable); return(ValueOrConverted(XmlExpressionConstants.ToSplittableStringArray(readStr, charsVariable))); } else { throw new NotImplementedException($"Cannot deserialize property {mapping.PropertyCache.Property}; array properties must contain a {nameof(SplittableStringAttribute)}."); } } else if (PropertyType.IsEnum) { return(ValueOrConverted(GetEnumSwitch(readStr, PropertyType))); } else if (PropertyType == typeof(int?)) { return(GetValue(XmlExpressionConstants.ToInt32, true)); } else if (PropertyType == typeof(double?)) { return(GetValue(XmlExpressionConstants.ToDouble, true)); } else if (PropertyType == typeof(bool?)) { return(GetValue(XmlExpressionConstants.ToBool, true)); } else if (PropertyType == typeof(DateTime?)) { return(GetValue(XmlExpressionConstants.ToNullableDateTimeSkipCheck, true, XmlExpressionConstants.ToDouble, XmlExpressionConstants.ToDateTimeFromDouble)); } else if (PropertyType == typeof(TimeSpan?)) { return(GetValue(XmlExpressionConstants.ToTimeSpan, true, XmlExpressionConstants.ToInt32, XmlExpressionConstants.ToTimeSpanFromInt32)); } else { var underlying = Nullable.GetUnderlyingType(PropertyType); if (underlying != null && underlying.IsEnum) { return(GetNullableEnumSwitch(underlying, PropertyType)); } } if (PropertyType.GetTypeCache().GetAttribute <XmlRootAttribute>() != null) { var customTypeGenerator = new XmlSerializerGenerator(PropertyType, null, false); var customTypeLambda = customTypeGenerator.MakeReadElement(); return(Expression.Invoke(customTypeLambda, customTypeGenerator.GetInnerReadElementParameters(generator?.update ?? false, true))); } return(null); }