private IEnumerable <Expression> CreateUnpackExpressions(ParameterExpression unpackerParameter, ParameterExpression itemSerializersParameter, Type[] itemSerializerTypes, IList <Type> flattenTypes)
 {
     for (int number = 0; number < flattenTypes.Count; number++)
     {
         /*
          *  checked
          *  {
          *		if (!unpacker.Read())
          *		{
          *			throw SerializationExceptions.NewMissingItem(0);
          *		}
          *
          *		T1 item1;
          *		if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader)
          *		{
          *			item1 = this._serializer0.UnpackFrom(unpacker);
          *		}
          *		else
          *		{
          *			using (Unpacker subtreeUnpacker = unpacker.ReadSubtree())
          *			{
          *				item1 = this._serializer0.UnpackFrom(subtreeUnpacker);
          *			}
          *		}
          *
          *		if (!unpacker.Read())
          *			:
          *
          *		return new Tuple<...>( item1, ... , new Tuple<...>(...)...);
          *	}
          */
         // Express above statement as expressions like functional.
         yield return
             (Expression.Block(
                  flattenTypes[number],
                  Expression.IfThen(
                      Expression.IsFalse(
                          Expression.Call(
                              unpackerParameter,
                              Metadata._Unpacker.Read
                              )
                          ),
                      Expression.Call(
                          SerializationExceptions.NewMissingItemMethod,
                          Expression.Constant(number)
                          )
                      ),
                  ExpressionSerializerLogics.CreateUnpackItem(
                      unpackerParameter,
                      Metadata._UnpackHelpers.InvokeUnpackFrom_1Method.MakeGenericMethod(flattenTypes[number]),
                      Expression.ArrayIndex(
                          itemSerializersParameter,
                          Expression.Constant(number)
                          ),
                      itemSerializerTypes[number]
                      )
                  ));
     }
 }
예제 #2
0
        public ListExpressionMessagePackSerializer(SerializationContext context, CollectionTraits traits)
            : base(context, traits)
        {
            Type type = typeof(T);

            if (type.GetIsAbstract())
            {
                type = context.DefaultCollectionTypes.GetConcreteType(typeof(T)) ?? type;
            }

            if (type.IsArray)
            {
                var capacityParameter = Expression.Parameter(typeof(int), "length");
                this._createInstanceWithCapacity =
                    Expression.Lambda <Func <int, T> >(
                        Expression.NewArrayBounds(type.GetElementType(), capacityParameter),
                        capacityParameter
                        ).Compile();
                this._createInstance = null;
            }
            else if (type.GetIsAbstract())
            {
                this._createInstance             = () => { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type); };
                this._createInstanceWithCapacity = null;
            }
            else
            {
                var constructor = ExpressionSerializerLogics.GetCollectionConstructor(context, type);
                if (constructor == null)
                {
                    this._createInstance             = () => { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(type); };
                    this._createInstanceWithCapacity = null;
                }
                else
                {
                    if (constructor.GetParameters().Length == 1)
                    {
                        this._createInstance = null;

                        var capacityParameter = Expression.Parameter(typeof(int), "parameter");
                        this._createInstanceWithCapacity =
                            Expression.Lambda <Func <int, T> >(
                                Expression.New(constructor, capacityParameter),
                                capacityParameter
                                ).Compile();
                    }
                    else
                    {
                        this._createInstanceWithCapacity = null;
                        this._createInstance             =
                            Expression.Lambda <Func <T> >(
                                Expression.New(constructor)
                                ).Compile();
                    }
                }
            }
        }
예제 #3
0
 /// <summary>
 ///		Creates an <see cref="Expression"/> which unpack an item.
 /// </summary>
 /// <param name="unpackerParameter">The parameter <see cref="Expression"/> which holds the unpacker.</param>
 /// <param name="unpackFrom">The target <c>UnpackFrom</c> method of the serializer for item type.</param>
 /// <param name="serializerParameter">The parameter <see cref="Expression"/> which has <c>UnpackFrom </c>will be invoked.</param>
 /// <param name="serializerType">The type of the item serializer.</param>
 /// <returns>An <see cref="Expression"/> which unpack an item.</returns>
 public static Expression CreateUnpackItem(Expression unpackerParameter, MethodInfo unpackFrom, Expression serializerParameter, Type serializerType)
 {
     return
         (Expression.Condition(
              Expression.AndAlso(
                  Expression.IsFalse(
                      Expression.Property(unpackerParameter, Metadata._Unpacker.IsArrayHeader)
                      ),
                  Expression.IsFalse(
                      Expression.Property(unpackerParameter, Metadata._Unpacker.IsMapHeader)
                      )
                  ),
              unpackFrom.IsStatic
                                 ? Expression.Call(
                  null,
                  unpackFrom,
                  Expression.TypeAs(serializerParameter, serializerType),
                  unpackerParameter
                  ) : Expression.Call(
                  Expression.TypeAs(serializerParameter, serializerType),
                  unpackFrom,
                  unpackerParameter
                  ),
              ExpressionSerializerLogics.Using(
                  typeof(Unpacker),
                  unpackFrom.ReturnType,
                  Expression.Call(
                      unpackerParameter,
                      Metadata._Unpacker.ReadSubtree
                      ),
                  usingVariable =>
                  unpackFrom.IsStatic
                                                 ? Expression.Call(
                      null,
                      unpackFrom,
                      Expression.TypeAs(serializerParameter, serializerType),
                      usingVariable
                      ) : Expression.Call(
                      Expression.TypeAs(serializerParameter, serializerType),
                      unpackFrom,
                      usingVariable
                      )
                  )
              ));
 }
        protected SequenceExpressionMessagePackSerializer(SerializationContext context, CollectionTraits traits)
        {
            Contract.Assert(typeof(T).IsArray || typeof(IEnumerable).IsAssignableFrom(typeof(T)), typeof(T) + " is not array nor IEnumerable");
            this._traits            = traits;
            this._elementSerializer = context.GetSerializer(traits.ElementType);
            this._getCount          = ExpressionSerializerLogics.CreateGetCount <T>(traits);

            var packerParameter            = Expression.Parameter(typeof(Packer), "packer");
            var objectTreeParameter        = Expression.Parameter(typeof(T), "objectTree");
            var elementSerializerParameter = Expression.Parameter(typeof(IMessagePackSerializer), "elementSerializer");
            var elementSerializerType      = typeof(MessagePackSerializer <>).MakeGenericType(traits.ElementType);

            /*
             *	packer.PackArrayHeader( objectTree.Count() );
             *	foreach( var item in objectTree )
             *	{
             *		elementSerializer.PackTo( packer, item );
             *	}
             */
            var packToCore =
                Expression.Lambda <Action <Packer, T, IMessagePackSerializer> >(
                    Expression.Block(
                        Expression.Call(
                            packerParameter,
                            Metadata._Packer.PackArrayHeader,
                            ExpressionSerializerLogics.CreateGetCountExpression <T>(traits, objectTreeParameter)
                            ),
                        traits.AddMethod == null
                                                ? ExpressionSerializerLogics.For(
                            Expression.ArrayLength(objectTreeParameter),
                            indexVariable =>
                            Expression.Call(
                                Expression.TypeAs(elementSerializerParameter, elementSerializerType),
                                typeof(MessagePackSerializer <>).MakeGenericType(traits.ElementType).GetMethod("PackTo"),
                                packerParameter,
                                Expression.ArrayIndex(objectTreeParameter, indexVariable)
                                )
                            )
                                                : ExpressionSerializerLogics.ForEach(
                            objectTreeParameter,
                            traits,
                            elementVariable =>
                            Expression.Call(
                                Expression.TypeAs(elementSerializerParameter, elementSerializerType),
                                typeof(MessagePackSerializer <>).MakeGenericType(traits.ElementType).GetMethod("PackTo"),
                                packerParameter,
                                elementVariable
                                )
                            )
                        ),
                    packerParameter, objectTreeParameter, elementSerializerParameter
                    );

#if !SILVERLIGHT
            if (context.GeneratorOption == SerializationMethodGeneratorOption.CanDump)
            {
                this._packToCoreExpression = packToCore;
            }
#endif

            this._packToCore = packToCore.Compile();

            var unpackerParameter = Expression.Parameter(typeof(Unpacker), "unpacker");
            var instanceParameter = Expression.Parameter(typeof(T), "instance");
            var countParamter     = Expression.Parameter(typeof(int), "count");

            /*
             *	for ( int i = 0; i < count; i++ )
             *	{
             *		if ( !unpacker.Read() )
             *		{
             *			throw SerializationExceptions.NewMissingItem( i );
             *		}
             *
             *		T item;
             *		if ( !unpacker.IsArrayHeader && !unpacker.IsMapHeader )
             *		{
             *			item = this.ElementSerializer.UnpackFrom( unpacker );
             *		}
             *		else
             *		{
             *			using ( Unpacker subtreeUnpacker = unpacker.ReadSubtree() )
             *			{
             *				item = this.ElementSerializer.UnpackFrom( subtreeUnpacker );
             *			}
             *		}
             *
             *		instance[ i ] = item; -- OR -- instance.Add( item );
             *	}
             */

            // FIXME: use UnpackHelper
            Expression <Action <Unpacker, T, IMessagePackSerializer> > unpackToCore;

            if (typeof(T).IsArray)
            {
                unpackToCore =
                    Expression.Lambda <Action <Unpacker, T, IMessagePackSerializer> >(
                        Expression.Call(
                            null,
                            _UnpackHelpers.UnpackArrayTo_1.MakeGenericMethod(traits.ElementType),
                            unpackerParameter,
                            Expression.TypeAs(elementSerializerParameter, typeof(MessagePackSerializer <>).MakeGenericType(traits.ElementType)),
                            instanceParameter
                            ),
                        unpackerParameter, instanceParameter, elementSerializerParameter
                        );
            }
            else if (typeof(T).GetIsGenericType())
            {
                MethodInfo unpackCollectionToMethod;
                Type       delegateType;
                if (traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof(void))
                {
                    unpackCollectionToMethod = _UnpackHelpers.UnpackCollectionTo_1.MakeGenericMethod(traits.ElementType);
                    delegateType             = typeof(Action <>).MakeGenericType(traits.ElementType);
                }
                else
                {
                    unpackCollectionToMethod = _UnpackHelpers.UnpackCollectionTo_2.MakeGenericMethod(traits.ElementType, traits.AddMethod.ReturnType);
                    delegateType             = typeof(Func <,>).MakeGenericType(traits.ElementType, traits.AddMethod.ReturnType);
                }

                var itemParameter = Expression.Parameter(traits.ElementType, "item");
                unpackToCore =
                    Expression.Lambda <Action <Unpacker, T, IMessagePackSerializer> >(
                        Expression.Call(
                            null,
                            unpackCollectionToMethod,
                            unpackerParameter,
                            Expression.TypeAs(elementSerializerParameter, typeof(MessagePackSerializer <>).MakeGenericType(traits.ElementType)),
                            Expression.TypeAs(instanceParameter, typeof(IEnumerable <>).MakeGenericType(traits.ElementType)),
                            Expression.Lambda(
                                delegateType,
                                Expression.Call(
                                    instanceParameter,
                                    traits.AddMethod,
                                    itemParameter
                                    ),
                                itemParameter
                                )
                            ),
                        unpackerParameter, instanceParameter, elementSerializerParameter
                        );
            }
            else
            {
                MethodInfo unpackCollectionToMethod;
                Type       delegateType;
                if (traits.AddMethod.ReturnType == null || traits.AddMethod.ReturnType == typeof(void))
                {
                    unpackCollectionToMethod = _UnpackHelpers.UnpackNonGenericCollectionTo;
                    delegateType             = typeof(Action <>).MakeGenericType(traits.ElementType);
                }
                else
                {
                    unpackCollectionToMethod = _UnpackHelpers.UnpackNonGenericCollectionTo_1.MakeGenericMethod(traits.AddMethod.ReturnType);
                    delegateType             = typeof(Func <,>).MakeGenericType(traits.ElementType, traits.AddMethod.ReturnType);
                }

                var itemParameter = Expression.Parameter(traits.ElementType, "item");
                unpackToCore =
                    Expression.Lambda <Action <Unpacker, T, IMessagePackSerializer> >(
                        Expression.Call(
                            null,
                            unpackCollectionToMethod,
                            unpackerParameter,
                            Expression.TypeAs(instanceParameter, typeof(IEnumerable)),
                            Expression.Lambda(
                                delegateType,
                                Expression.Call(
                                    instanceParameter,
                                    traits.AddMethod,
                                    itemParameter
                                    ),
                                itemParameter
                                )
                            ),
                        unpackerParameter, instanceParameter, elementSerializerParameter
                        );
            }

#if !SILVERLIGHT
            if (context.GeneratorOption == SerializationMethodGeneratorOption.CanDump)
            {
                this._unpackToCoreExpression = unpackToCore;
            }
#endif

            this._unpackToCore = unpackToCore.Compile();
        }
        public MapExpressionMessagePackSerializer(SerializationContext context, CollectionTraits traits)
        {
            Contract.Assert(typeof(IEnumerable).IsAssignableFrom(typeof(T)), typeof(T) + " is IEnumerable");
            Contract.Assert(traits.ElementType == typeof(DictionaryEntry) || (traits.ElementType.GetIsGenericType() && traits.ElementType.GetGenericTypeDefinition() == typeof(KeyValuePair <,>)), "Element type " + traits.ElementType + " is not KeyValuePair<TKey,TValue>.");
            this._traits          = traits;
            this._keySerializer   = traits.ElementType.GetIsGenericType() ? context.GetSerializer(traits.ElementType.GetGenericArguments()[0]) : context.GetSerializer(typeof(MessagePackObject));
            this._valueSerializer = traits.ElementType.GetIsGenericType() ? context.GetSerializer(traits.ElementType.GetGenericArguments()[1]) : context.GetSerializer(typeof(MessagePackObject));
            this._getCount        = ExpressionSerializerLogics.CreateGetCount <T>(traits);

            var constructor = ExpressionSerializerLogics.GetCollectionConstructor <T>();

            if (constructor == null)
            {
                this._createInstance             = () => { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(typeof(T)); };
                this._createInstanceWithCapacity = null;
            }
            else if (constructor.GetParameters().Length == 1)
            {
                this._createInstance = null;

                var capacityParameter = Expression.Parameter(typeof(int), "parameter");
                this._createInstanceWithCapacity =
                    Expression.Lambda <Func <int, T> >(
                        Expression.New(constructor, capacityParameter),
                        capacityParameter
                        ).Compile();
            }
            else
            {
                this._createInstanceWithCapacity = null;
                this._createInstance             =
                    Expression.Lambda <Func <T> >(
                        Expression.New(constructor)
                        ).Compile();
            }

            var packerParameter          = Expression.Parameter(typeof(Packer), "packer");
            var objectTreeParameter      = Expression.Parameter(typeof(T), "objectTree");
            var keySerializerParameter   = Expression.Parameter(typeof(IMessagePackSerializer), "keySerializer");
            var valueSerializerParameter = Expression.Parameter(typeof(IMessagePackSerializer), "valueSerializer");
            var keyType             = traits.ElementType.GetIsGenericType() ? traits.ElementType.GetGenericArguments()[0] : typeof(MessagePackObject);
            var valueType           = traits.ElementType.GetIsGenericType() ? traits.ElementType.GetGenericArguments()[1] : typeof(MessagePackObject);
            var keySerializerType   = typeof(MessagePackSerializer <>).MakeGenericType(keyType);
            var valueSerializerType = typeof(MessagePackSerializer <>).MakeGenericType(valueType);

            /*
             *	packer.PackMapHeader( objectTree.Count() );
             *	foreach( var item in objectTree )
             *	{
             *		elementSerializer.PackTo( packer, item.Key );
             *		elementSerializer.PackTo( packer, item.Value );
             *	}
             */
            var packToCore =
                Expression.Lambda <Action <Packer, T, IMessagePackSerializer, IMessagePackSerializer> >(
                    Expression.Block(
                        Expression.Call(
                            packerParameter,
                            Metadata._Packer.PackMapHeader,
                            ExpressionSerializerLogics.CreateGetCountExpression <T>(traits, objectTreeParameter)
                            ),
                        ExpressionSerializerLogics.ForEach(
                            objectTreeParameter,
                            traits,
                            elementVariable =>
                            Expression.Block(
                                Expression.Call(
                                    Expression.TypeAs(keySerializerParameter, keySerializerType),
                                    typeof(MessagePackSerializer <>).MakeGenericType(keyType).GetMethod("PackTo"),
                                    packerParameter,
                                    traits.ElementType.GetIsGenericType()
                                                                                ? Expression.Property(elementVariable, traits.ElementType.GetProperty("Key")) as Expression
                                                                                : Expression.Unbox(Expression.Property(elementVariable, traits.ElementType.GetProperty("Key")), typeof(MessagePackObject))
                                    ),
                                Expression.Call(
                                    Expression.TypeAs(valueSerializerParameter, valueSerializerType),
                                    typeof(MessagePackSerializer <>).MakeGenericType(valueType).GetMethod("PackTo"),
                                    packerParameter,
                                    traits.ElementType.GetIsGenericType()
                                                                                ? Expression.Property(elementVariable, traits.ElementType.GetProperty("Value")) as Expression
                                                                                : Expression.Unbox(Expression.Property(elementVariable, traits.ElementType.GetProperty("Value")), typeof(MessagePackObject))
                                    )
                                )
                            )
                        ), packerParameter, objectTreeParameter, keySerializerParameter, valueSerializerParameter
                    );

#if !SILVERLIGHT
            if (context.GeneratorOption == SerializationMethodGeneratorOption.CanDump)
            {
                this._packToCoreExpression = packToCore;
            }
#endif

            this._packToCore = packToCore.Compile();

            var unpackerParameter = Expression.Parameter(typeof(Unpacker), "unpacker");
            var instanceParameter = Expression.Parameter(typeof(T), "instance");
            var countParamter     = Expression.Parameter(typeof(int), "count");

            Expression <Action <Unpacker, T, IMessagePackSerializer, IMessagePackSerializer> > unpackToCore;
            if (traits.ElementType.GetIsGenericType())
            {
                /*
                 * UnpackHelpers.UnpackMapTo<TKey,TValue>( unpacker, keySerializer, valueSerializer, instance );
                 */
                unpackToCore =
                    Expression.Lambda <Action <Unpacker, T, IMessagePackSerializer, IMessagePackSerializer> >(
                        Expression.Call(
                            Metadata._UnpackHelpers.UnpackMapTo_2.MakeGenericMethod(keyType, valueType),
                            unpackerParameter,
                            Expression.TypeAs(keySerializerParameter, keySerializerType),
                            Expression.TypeAs(valueSerializerParameter, valueSerializerType),
                            Expression.TypeAs(instanceParameter, typeof(IDictionary <,>).MakeGenericType(keyType, valueType))
                            ),
                        unpackerParameter, instanceParameter, keySerializerParameter, valueSerializerParameter
                        );
            }
            else
            {
                /*
                 * UnpackHelpers.UnpackNonGenericMapTo( unpacker, instance );
                 */
                unpackToCore =
                    Expression.Lambda <Action <Unpacker, T, IMessagePackSerializer, IMessagePackSerializer> >(
                        Expression.Call(
                            Metadata._UnpackHelpers.UnpackNonGenericMapTo,
                            unpackerParameter,
                            Expression.TypeAs(instanceParameter, typeof(IDictionary))
                            ),
                        unpackerParameter, instanceParameter, keySerializerParameter, valueSerializerParameter
                        );
            }

#if !SILVERLIGHT
            if (context.GeneratorOption == SerializationMethodGeneratorOption.CanDump)
            {
                this._unpackToCoreExpression = unpackToCore;
            }
#endif

            this._unpackToCore = unpackToCore.Compile();
        }