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