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 /// /// 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 Expression MakeNullableEnumLambda(Type underlyingType, Type nullableType) { var str = Expression.Parameter(typeof(string), "str"); var isNullOrEmpty = Expression.Call(XmlSerializerMembers.String_IsNullOrEmpty, str); var @null = Expression.Constant(null, nullableType); var val = GetEnumSwitch(str, underlyingType); var cast = Expression.Convert(val, nullableType); var condition = Expression.Condition( isNullOrEmpty, //if (string.IsNullOrEmpty(str) @null, // return null; cast //return ToEnum(str) ); var lambda = Expression.Lambda( Expression.Block( condition ), $"ReadNullable{underlyingType.Name}", new[] { str, XmlExpressionConstants.Serializer } ); return(XmlSerializerGenerator.LambdaOrDelegate(lambda)); }
public ValueDeserializer( XmlMapping mapping, XmlSerializerGenerator generator, Expression str) { this.mapping = mapping; this.generator = generator; PropertyType = mapping.PropertyCache.Property.PropertyType; valueConverter = GetValueConverter(); readStr = str; }
private Expression MakeEnumLambda(Type type) { var p = Expression.Parameter(typeof(string), "s"); var c = ReflectionCacheManager.GetEnumCache(type).Cache; var fields = c.Fields; List <SwitchCase> cases = new List <SwitchCase>(); foreach (var f in fields) { if (f.Field.FieldType.IsEnum) { var val = f.Field.GetValue(null); var caseConditions = f.Attributes.Where(v => v.Key == typeof(XmlEnumAttribute) || v.Key == typeof(XmlEnumAlternateName)) .SelectMany(a => a.Value).Cast <XmlEnumAttribute>().Select(a => Expression.Constant(a.Name)).ToArray(); if (caseConditions.Length > 0) { cases.Add(Expression.SwitchCase(Expression.Constant(val), caseConditions)); } } } var failEnum = XmlExpressionConstants.FailEnum(p, type); var throwFailEnum = Expression.Throw(failEnum, type); Expression switchBody; if (cases.Count > 0) { switchBody = Expression.Switch(p, throwFailEnum, cases.ToArray()); } else { switchBody = throwFailEnum; } var lambda = Expression.Lambda( Expression.Block(switchBody), $"Read{type.Name}", new[] { p, XmlExpressionConstants.Serializer }); return(XmlSerializerGenerator.LambdaOrDelegate(lambda)); }
private Expression MakeNullableMethod( Func <Expression, MethodCallExpression> deserializeString, Func <Expression, MethodCallExpression> deserializeToConverter, Func <Expression, MethodCallExpression> deserializeFromConverter) { var parameter = Expression.Parameter(typeof(string), "str"); var isNullOrEmpty = Expression.Call(XmlSerializerMembers.String_IsNullOrEmpty, parameter); var assignment = parameter.Assign(XmlExpressionConstants.ToNullableString(parameter)); var eval = ConvertValue(parameter, deserializeString, deserializeToConverter, deserializeFromConverter); var nullableType = eval.Type; //Generally speaking, eval.Type is not the nullable type. It's only nullable //when a special deserializeFromConverter method has been specified (such as in the case of //nullable DateTime) if (Nullable.GetUnderlyingType(nullableType) == null) { nullableType = typeof(Nullable <>).MakeGenericType(eval.Type); } var condition = Expression.Condition( isNullOrEmpty, //string.IsNullOrEmpty(str) Expression.Constant(null, nullableType), Expression.Convert(eval, nullableType) ); var name = $"ToNullable{eval.Type.Name}"; if (valueConverter != null) { name += "_With" + converterType.Name; } var lambda = Expression.Lambda( Expression.Block(condition), name, new[] { parameter, XmlExpressionConstants.Serializer } ); return(XmlSerializerGenerator.LambdaOrDelegate(lambda)); }
public ValueDeserializer(XmlMapping mapping, XmlSerializerGenerator generator) : this(mapping, generator, null) { readStr = ReadString(); }
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 LadderCondition(XmlMapping mapping, int mappingIndex, XmlSerializerGenerator generator) { this.mapping = mapping; this.mappingIndex = mappingIndex; this.generator = generator; }
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); }
public LadderBuilder(XmlSerializerGenerator generator, XmlAttributeType attributeType) { this.generator = generator; this.attributeType = attributeType; }