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] ) )); } }
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(); } } } }
/// <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(); }