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);
        }
Пример #3
0
        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);
        }