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);
        }
Exemple #11
0
 public LadderBuilder(XmlSerializerGenerator generator, XmlAttributeType attributeType)
 {
     this.generator     = generator;
     this.attributeType = attributeType;
 }