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