private void BuildTupleSerializer(TContext context, IList <PolymorphismSchema> itemSchemaList) { var itemTypes = TupleItems.GetTupleItemTypes(typeof(TObject)); this.BuildTuplePackTo(context, itemTypes, itemSchemaList); this.BuildTupleUnpackFrom(context, itemTypes, itemSchemaList); }
public static SerializerEmitter CreateTupleSerializerCore(Type tupleType, EmitterFlavor emitterFlavor) { Contract.Requires(tupleType != null); Contract.Ensures(Contract.Result <SerializerEmitter>() != null); var emitter = SerializationMethodGeneratorManager.Get().CreateEmitter(tupleType, emitterFlavor); var itemTypes = TupleItems.GetTupleItemTypes(tupleType); CreateTuplePack( emitter, tupleType, itemTypes, (il, collection) => { il.EmitAnyLdarg(2); il.EmitAnyStloc(collection); } ); CreateTupleUnpack( emitter, itemTypes ); return(emitter); }
private IEnumerable <Expression> CreateTupleItemExpressions(ParameterExpression objectTreeParameter, IList <Type> flattenTypes) { var tupleTypeList = TupleItems.CreateTupleTypeList(flattenTypes); int depth = -1; for (int i = 0; i < flattenTypes.Count; i++) { if (i % 7 == 0) { depth++; } Expression current = objectTreeParameter; for (int j = 0; j < depth; j++) { // .TRest.TRest ... var rest = tupleTypeList[j].GetProperty("Rest"); current = Expression.Property(current, rest); } var itemn = tupleTypeList[depth].GetProperty("Item" + ((i % 7) + 1)); #if DEBUG Contract.Assert(itemn != null, tupleTypeList[depth].GetFullName() + "::Item" + ((i % 7) + 1) + " [ " + depth + " ] @ " + i); #endif yield return(Expression.Property(current, itemn)); } }
private void BuildTupleSerializer(TContext context, IList <PolymorphismSchema> itemSchemaList, out SerializationTarget targetInfo) { var itemTypes = TupleItems.GetTupleItemTypes(this.TargetType); targetInfo = SerializationTarget.CreateForTuple(itemTypes); var isValueTuple = this.TargetType.GetIsValueType(); this.BuildTuplePackTo(context, itemTypes, itemSchemaList, isValueTuple, false); #if FEATURE_TAP if (this.WithAsync(context)) { this.BuildTuplePackTo(context, itemTypes, itemSchemaList, isValueTuple, true); } #endif // FEATURE_TAP this.BuildTupleUnpackFrom(context, itemTypes, itemSchemaList, isValueTuple, false); #if FEATURE_TAP if (this.WithAsync(context)) { this.BuildTupleUnpackFrom(context, itemTypes, itemSchemaList, isValueTuple, true); } #endif // FEATURE_TAP }
private void BuildTupleSerializer(TContext context) { var itemTypes = TupleItems.GetTupleItemTypes(typeof(TObject)); this.BuildTuplePackTo(context, itemTypes); this.BuildTupleUnpackFrom(context, itemTypes); }
internal static MessagePackSerializer <T> CreateReflectionInternal <T>(SerializationContext context, Type concreteType, PolymorphismSchema schema) { if (concreteType.GetIsAbstract() || concreteType.GetIsInterface()) { // return null for polymoirphic provider. return(null); } var serializer = context.Serializers.Get <T>(context); if (serializer != null) { // For MessagePack.Create compatibility. // Required for built-in types. return(serializer); } ValidateType(typeof(T)); var traits = typeof(T).GetCollectionTraits(); switch (traits.CollectionType) { case CollectionKind.Array: case CollectionKind.Map: { return (#if !UNITY ReflectionSerializerHelper.CreateCollectionSerializer <T>(context, concreteType, traits, (schema ?? PolymorphismSchema.Default))); #else Wrap <T>( context, ReflectionSerializerHelper.CreateCollectionSerializer <T>(context, concreteType, traits, (schema ?? PolymorphismSchema.Default)) ); #endif // !UNITY } default: { if (typeof(T).GetIsEnum()) { return(ReflectionSerializerHelper.CreateReflectionEnumMessagePackSerializer <T>(context)); } #if !WINDOWS_PHONE && !NETFX_35 && !UNITY if (TupleItems.IsTuple(typeof(T))) { return (new ReflectionTupleMessagePackSerializer <T>( context, (schema ?? PolymorphismSchema.Default).ChildSchemaList )); } #endif // !WINDOWS_PHONE && !NETFX_35 && !UNITY return(new ReflectionObjectMessagePackSerializer <T>(context)); } } }
public ReflectionTupleMessagePackSerializer(SerializationContext ownerContext) : base(ownerContext) { var itemTypes = TupleItems.GetTupleItemTypes(typeof(T)); this._itemSerializers = itemTypes.Select(itemType => ownerContext.GetSerializer(itemType)).ToArray(); this._tupleTypes = TupleItems.CreateTupleTypeList(itemTypes); this._tupleConstructors = this._tupleTypes.Select(tupleType => tupleType.GetConstructors().Single()).ToArray(); this._getters = GetGetters(itemTypes, this._tupleTypes).ToArray(); }
public ReflectionTupleMessagePackSerializer(SerializationContext ownerContext, IList <PolymorphismSchema> itemSchemas) : base(ownerContext) { var itemTypes = TupleItems.GetTupleItemTypes(typeof(T)); this._itemSerializers = itemTypes.Select( (itemType, i) => ownerContext.GetSerializer(itemType, itemSchemas.Count == 0 ? null : itemSchemas[i]) ).ToArray(); this._tupleTypes = TupleItems.CreateTupleTypeList(itemTypes); this._tupleConstructors = this._tupleTypes.Select(tupleType => tupleType.GetConstructors().Single()).ToArray(); this._getters = GetGetters(itemTypes, this._tupleTypes).ToArray(); }
private static void VerifyArity(Type tupleType, ICollection <PolymorphismSchema> itemSchemaList) { if (itemSchemaList == null || itemSchemaList.Count == 0) { // OK return; } if (TupleItems.GetTupleItemTypes(tupleType).Count != itemSchemaList.Count) { throw new ArgumentException("An arity of itemSchemaList does not match for an arity of the tuple.", "itemSchemaList"); } }
private IEnumerable <TConstruct> BuildTuplePackToCore(TContext context, IList <Type> itemTypes, IList <PolymorphismSchema> itemSchemaList) { // Put cardinality as array length. yield return(this.EmitPutArrayHeaderExpression(context, this.MakeInt32Literal(context, itemTypes.Count))); var depth = -1; var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); var propertyInvocationChain = new List <PropertyInfo>(itemTypes.Count % 7 + 1); for (int i = 0; i < itemTypes.Count; i++) { if (i % 7 == 0) { depth++; } for (int j = 0; j < depth; j++) { // .TRest.TRest ... var restProperty = tupleTypeList[j].GetProperty("Rest"); #if DEBUG Contract.Assert(restProperty != null); #endif propertyInvocationChain.Add(restProperty); } var itemNProperty = tupleTypeList[depth].GetProperty("Item" + ((i % 7) + 1)); propertyInvocationChain.Add(itemNProperty); #if DEBUG Contract.Assert( itemNProperty != null, tupleTypeList[depth].GetFullName() + "::Item" + ((i % 7) + 1) + " [ " + depth + " ] @ " + i); #endif foreach (var packTupleItem in this.EmitPackTupleItemStatements( context, itemTypes[i], context.Packer, context.PackToTarget, propertyInvocationChain, itemSchemaList.Count == 0 ? null : itemSchemaList[i] ) ) { yield return(packTupleItem); } propertyInvocationChain.Clear(); } }
public ReflectionTupleMessagePackSerializer(SerializationContext ownerContext, IList <PolymorphismSchema> itemSchemas) : base(ownerContext, SerializerCapabilities.PackTo | SerializerCapabilities.UnpackFrom) { var itemTypes = TupleItems.GetTupleItemTypes(typeof(T)); this._itemSerializers = itemTypes.Select( (itemType, i) => ownerContext.GetSerializer(itemType, itemSchemas.Count == 0 ? null : itemSchemas[i]) ).ToArray(); this._tupleTypes = TupleItems.CreateTupleTypeList(typeof(T)); this._tupleConstructors = this._tupleTypes.Select(tupleType => tupleType.GetConstructors().SingleOrDefault()).ToArray(); this._getters = typeof(T).GetIsValueType() ? GetGetters( itemTypes, this._tupleTypes, (type, name) => type.GetField(name), f => f, getters => tuple => { object current = tuple; foreach (var getter in getters) { current = getter.GetValue(current); } return(current); } ).ToArray() : GetGetters( itemTypes, this._tupleTypes, (type, name) => type.GetProperty(name), p => p.GetGetMethod(), getters => tuple => { object current = tuple; foreach (var getter in getters) { current = getter.InvokePreservingExceptionType(current); } return(current); } ).ToArray(); }
/// <summary> /// Builds the serializer and returns its new instance. /// </summary> /// <param name="context">The context information. This value will not be <c>null</c>.</param> /// <param name="concreteType">The substitution type if <see cref="TargetType"/> is abstract type. <c>null</c> when <see cref="TargetType"/> is not abstract type.</param> /// <param name="schema">The schema which contains schema for collection items, dictionary keys, or tuple items. This value may be <c>null</c>.</param> /// <param name="targetInfo">The parsed serialization target information.</param> /// <returns> /// Newly created serializer object. /// This value will not be <c>null</c>. /// </returns> protected void BuildSerializer(TContext context, Type concreteType, PolymorphismSchema schema, out SerializationTarget targetInfo) { #if DEBUG Contract.Assert(!this.TargetType.IsArray); Contract.Assert(!this.TargetType.GetIsEnum()); #endif switch (this.CollectionTraits.CollectionType) { case CollectionKind.Array: case CollectionKind.Map: { targetInfo = null; this.BuildCollectionSerializer(context, concreteType, schema); break; } case CollectionKind.NotCollection: { var nullableUnderlyingType = Nullable.GetUnderlyingType(this.TargetType); if (nullableUnderlyingType != null) { targetInfo = null; this.BuildNullableSerializer(context, nullableUnderlyingType); } #if !NETFX_35 else if (TupleItems.IsTuple(this.TargetType)) { this.BuildTupleSerializer(context, (schema ?? PolymorphismSchema.Default).ChildSchemaList, out targetInfo); } #endif else { #if DEBUG Contract.Assert(schema == null || schema.UseDefault); #endif // DEBUG this.BuildObjectSerializer(context, out targetInfo); } break; } default: { throw new NotSupportedException("Unknown traits :" + this.CollectionTraits); } } }
private Expression CreateNestedTupleCreationExpression(IList <Type> itemTypes, IEnumerable <Expression> itemExpressions) { var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); Expression right = null; for (int depth = tupleTypeList.Count - 1; 0 <= depth; depth--) { var constructor = tupleTypeList[depth].GetConstructors().Single(); var args = itemExpressions.Skip(depth * 7).Take(Math.Min(constructor.GetParameters().Length, 7)); if (right != null) { args = args.Concat(new[] { right }); } right = Expression.New(constructor, args); } return(right); }
/// <summary> /// Builds the serializer and returns its new instance. /// </summary> /// <param name="context">The context information. This value will not be <c>null</c>.</param> /// <param name="concreteType">The substitution type if <typeparamref name="TObject"/> is abstract type. <c>null</c> when <typeparamref name="TObject"/> is not abstract type.</param> /// <param name="schema">The schema which contains schema for collection items, dictionary keys, or tuple items. This value may be <c>null</c>.</param> /// <returns> /// Newly created serializer object. /// This value will not be <c>null</c>. /// </returns> protected void BuildSerializer(TContext context, Type concreteType, PolymorphismSchema schema) { #if DEBUG Contract.Assert(!typeof(TObject).IsArray); Contract.Assert(!typeof(TObject).GetIsEnum()); #endif switch (CollectionTraitsOfThis.CollectionType) { case CollectionKind.Array: case CollectionKind.Map: { this.BuildCollectionSerializer(context, concreteType, schema); break; } case CollectionKind.NotCollection: { var nullableUnderlyingType = Nullable.GetUnderlyingType(typeof(TObject)); if (nullableUnderlyingType != null) { this.BuildNullableSerializer(context, nullableUnderlyingType); } #if !NETFX_35 else if (TupleItems.IsTuple(typeof(TObject))) { this.BuildTupleSerializer(context, (schema ?? PolymorphismSchema.Default).ChildSchemaList); } #endif else { #if DEBUG && !UNITY Contract.Assert(schema == null || schema.UseDefault); #endif // DEBUG this.BuildObjectSerializer(context); } break; } } }
private IEnumerable <TConstruct> BuildTuplePackToCore(TContext context, IList <Type> itemTypes, IList <PolymorphismSchema> itemSchemaList, bool isAsync) { // Note: cardinality is put as array length by PackHelper. var depth = -1; var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); var propertyInvocationChain = new List <PropertyInfo>(itemTypes.Count % 7 + 1); var packValueArguments = new[] { context.Packer, context.PackToTarget } #if FEATURE_TAP .Concat(isAsync ? new[] { this.ReferCancellationToken(context, 3) } : NoConstructs).ToArray() #endif // FEATURE_TAP ; for (int i = 0; i < itemTypes.Count; i++) { if (i % 7 == 0) { depth++; } for (int j = 0; j < depth; j++) { // .TRest.TRest ... var restProperty = tupleTypeList[j].GetProperty("Rest"); #if DEBUG Contract.Assert(restProperty != null); #endif propertyInvocationChain.Add(restProperty); } var itemNProperty = tupleTypeList[depth].GetProperty("Item" + ((i % 7) + 1)); propertyInvocationChain.Add(itemNProperty); #if DEBUG Contract.Assert( itemNProperty != null, tupleTypeList[depth].GetFullName() + "::Item" + ((i % 7) + 1) + " [ " + depth + " ] @ " + i ); #endif var count = i; this.ExtractPrivateMethod( context, AdjustName(MethodNamePrefix.PackValue + SerializationTarget.GetTupleItemNameFromIndex(i), isAsync), #if FEATURE_TAP isAsync ? typeof(Task) : #endif // FEATURE_TAP typeof(void), () => this.EmitSequentialStatements( context, typeof(void), this.EmitPackTupleItemStatements( context, itemTypes[count], context.Packer, context.PackToTarget, propertyInvocationChain, itemSchemaList.Count == 0 ? null : itemSchemaList[count], isAsync ) ), packValueArguments ); propertyInvocationChain.Clear(); } var packHelperArguments = new[] { context.Packer, context.PackToTarget, this.EmitGetActionsExpression(context, ActionType.PackToArray, isAsync) } #if FEATURE_TAP .Concat(isAsync ? new[] { this.ReferCancellationToken(context, 3) } : NoConstructs).ToArray() #endif // FEATURE_TAP ; var packToArray = this.EmitInvokeMethodExpression( context, null, new MethodDefinition( AdjustName(MethodName.PackToArray, isAsync), new [] { TypeDefinition.Object(this.TargetType) }, typeof(PackHelpers), #if FEATURE_TAP isAsync ? typeof(Task) : #endif // FEATURE_TAP typeof(void), packHelperArguments.Select(a => a.ContextType).ToArray() ), packHelperArguments ); if (isAsync) { // Wrap with return to return Task packToArray = this.EmitRetrunStatement(context, packToArray); } yield return(packToArray); }
public TupleExpressionMessagePackSerializer(SerializationContext context) : base((context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions) { Contract.Assert(typeof(T).FullName.StartsWith("System.Tuple`", StringComparison.Ordinal), typeof(T) + " is not Tuple<...>"); var flattenTypes = TupleItems.GetTupleItemTypes(typeof(T)); this._itemSerializers = flattenTypes.Select(t => context.GetSerializer(t)).ToArray(); var packerParameter = Expression.Parameter(typeof(Packer), "packer"); var objectTreeParameter = Expression.Parameter(typeof(T), "objectTree"); var itemSerializersParameter = Expression.Parameter(typeof(IMessagePackSerializer[]), "itemSerializers"); var itemSerializerTypes = flattenTypes.Select(t => typeof(MessagePackSerializer <>).MakeGenericType(t)).ToArray(); /* * packer.PackArrayHeader( arity ); * serializer[ 0 ].PackTo( pack, tuple.Item1 ); * : * serializer[ N ].PackTo( pack, tuple.Rest....ItemM ); */ this._packToCore = Expression.Lambda <Action <Packer, T, IMessagePackSerializer[]> >( Expression.Block( new[] { Expression.Call( packerParameter, Metadata._Packer.PackArrayHeader, Expression.Constant(flattenTypes.Count) ) }.Concat( CreatePackExpressions(packerParameter, objectTreeParameter, itemSerializersParameter, itemSerializerTypes, flattenTypes) ).ToArray() ), packerParameter, objectTreeParameter, itemSerializersParameter ).Compile(); var unpackerParameter = Expression.Parameter(typeof(Unpacker), "unpacker"); /* * 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<...>(...)...); * } */ this._unpackFromCore = Expression.Lambda <Func <Unpacker, IMessagePackSerializer[], T> >( CreateNestedTupleCreationExpression( flattenTypes, CreateUnpackExpressions(unpackerParameter, itemSerializersParameter, itemSerializerTypes, flattenTypes).ToArray() ), unpackerParameter, itemSerializersParameter ).Compile(); }
private static void CreateTupleUnpackFrom(SerializerEmitter emitter, IList <Type> itemTypes) { var il = emitter.GetUnpackFromMethodILGenerator(); var localHolder = new LocalVariableHolder(il); try { /* * checked * { * if (!unpacker.IsArrayHeader) * { * throw SerializationExceptions.NewIsNotArrayHeader(); * } * * if ((int)unpacker.ItemsCount != n) * { * throw SerializationExceptions.NewTupleCardinarityIsNotMatch(n, (int)unpacker.ItemsCount); * } * * if (!unpacker.Read()) * { * throw SerializationExceptions.NewMissingItem(0); * } * * DESERIALIZE_VALUE * * : * * return new Tuple<...>( item1, ... , new Tuple<...>(...)...); * } */ il.EmitAnyLdarg(1); il.EmitGetProperty(Metadata._Unpacker.IsArrayHeader); var endIf = il.DefineLabel("END_IF"); il.EmitBrtrue_S(endIf); il.EmitAnyCall(SerializationExceptions.NewIsNotArrayHeaderMethod); il.EmitThrow(); il.MarkLabel(endIf); var itemsCount = localHolder.ItemsCount; Emittion.EmitGetUnpackerItemsCountAsInt32(il, 1, localHolder); il.EmitAnyLdc_I4(itemTypes.Count); il.EmitAnyStloc(itemsCount); il.EmitAnyLdloc(itemsCount); var endIf1 = il.DefineLabel("END_IF1"); il.EmitBeq_S(endIf1); il.EmitAnyLdc_I4(itemTypes.Count); il.EmitAnyLdloc(itemsCount); il.EmitAnyCall(SerializationExceptions.NewTupleCardinarityIsNotMatchMethod); il.EmitThrow(); il.MarkLabel(endIf1); var itemLocals = new LocalBuilder[itemTypes.Count]; var useDummyNullables = new bool[itemTypes.Count]; for (int i = 0; i < itemTypes.Count; i++) { if (itemTypes[i] != typeof(MessagePackObject) && itemTypes[i].GetIsValueType() && Nullable.GetUnderlyingType(itemTypes[i]) == null) { // Use temporary nullable value for nil implication. itemLocals[i] = il.DeclareLocal(typeof(Nullable <>).MakeGenericType(itemTypes[i]), "item" + i.ToString(CultureInfo.InvariantCulture)); useDummyNullables[i] = true; } else { itemLocals[i] = il.DeclareLocal(itemTypes[i], "item" + i.ToString(CultureInfo.InvariantCulture)); } // Tuple member should be NilImplication.MemberDefault. Emittion.EmitDeserializeValueWithoutNilImplication(emitter, il, 1, itemLocals[i], typeof(Tuple), "Item" + (i).ToString(CultureInfo.InvariantCulture), localHolder); } for (int i = 0; i < itemLocals.Length; i++) { if (useDummyNullables[i]) { il.EmitAnyLdloca(itemLocals[i]); il.EmitGetProperty(typeof(Nullable <>).MakeGenericType(itemTypes[i]).GetProperty("Value")); } else { il.EmitAnyLdloc(itemLocals[i]); } } var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); for (int depth = tupleTypeList.Count - 1; 0 <= depth; depth--) { il.EmitNewobj(tupleTypeList[depth].GetConstructors().Single()); } il.EmitRet(); } finally { il.FlushTrace(); } }
private static void CreateTuplePack(SerializerEmitter emiter, Type tupleType, IList <Type> itemTypes, Action <TracingILGenerator, LocalBuilder> loadTupleEmitter) { var il = emiter.GetPackToMethodILGenerator(); var localHolder = new LocalVariableHolder(il); try { /* * packer.PackArrayHeader( cardinarity ); * _serializer0.PackTo( packer, tuple.Item1 ); * : * _serializer6.PackTo( packer, tuple.item7 ); * _serializer7.PackTo( packer, tuple.Rest.Item1 ); */ var tuple = il.DeclareLocal(tupleType, "tuple"); loadTupleEmitter(il, tuple); il.EmitAnyLdarg(1); il.EmitAnyLdc_I4(itemTypes.Count); il.EmitAnyCall(Metadata._Packer.PackArrayHeader); il.EmitPop(); var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); int depth = -1; for (int i = 0; i < itemTypes.Count; i++) { if (i % 7 == 0) { depth++; } Emittion.EmitSerializeValue( emiter, il, 1, itemTypes[i], null, NilImplication.MemberDefault, il0 => { il0.EmitAnyLdloc(tuple); for (int j = 0; j < depth; j++) { // .TRest.TRest ... var rest = tupleTypeList[j].GetProperty("Rest"); il0.EmitGetProperty(rest); } var itemn = tupleTypeList[depth].GetProperty("Item" + ((i % 7) + 1)); #if DEBUG Contract.Assert(itemn != null, tupleTypeList[depth].GetFullName() + "::Item" + ((i % 7) + 1) + " [ " + depth + " ] @ " + i); #endif il0.EmitGetProperty(itemn); }, localHolder ); } il.EmitRet(); } finally { il.FlushTrace(); } }
private IEnumerable <TConstruct> BuildTupleUnpackFromCore(TContext context, IList <Type> itemTypes) { var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); yield return (this.EmitCheckIsArrayHeaderExpression(context, context.Unpacker)); yield return (this.EmitCheckTupleCardinarityExpression( context, context.Unpacker, itemTypes.Count )); var unpackedItems = itemTypes.Select( (type, i) => this.DeclareLocal( context, type, "item" + i ) ).ToArray(); var unpackItems = itemTypes.Select( (unpackedNullableItemType, i) => this.EmitUnpackItemValueExpression( context, unpackedNullableItemType, context.TupleItemNilImplication, context.Unpacker, this.MakeInt32Literal(context, i), this.MakeStringLiteral(context, "Item" + i.ToString(CultureInfo.InvariantCulture)), null, null, null, unpackedItem => this.EmitStoreVariableStatement( context, unpackedItems[i], unpackedItem ) ) ); TConstruct currentTuple = null; for (int nest = tupleTypeList.Count - 1; nest >= 0; nest--) { var items = unpackedItems.Skip(nest * 7).Take(Math.Min(unpackedItems.Length, 7)); currentTuple = this.EmitCreateNewObjectExpression( context, null, // Tuple is reference contextType. tupleTypeList[nest].GetConstructors().Single(), currentTuple == null ? items.ToArray() : items.ToArray().Concat(new[] { currentTuple }).ToArray() ); } #if DEBUG Contract.Assert(currentTuple != null); #endif yield return (this.EmitSequentialStatements( context, typeof(TObject), unpackedItems.Concat(unpackItems).Concat(new[] { this.EmitRetrunStatement(context, currentTuple) }) )); }
private IEnumerable <TConstruct> BuildTupleUnpackFromCore(TContext context, IList <Type> itemTypes, IList <PolymorphismSchema> itemSchemaList, bool isAsync) { var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); yield return (this.EmitCheckIsArrayHeaderExpression(context, context.Unpacker)); yield return (this.EmitCheckTupleCardinarityExpression( context, context.Unpacker, itemTypes.Count )); var unpackingContext = this.GetTupleUnpackingContextInfo(context, itemTypes); foreach (var statement in unpackingContext.Statements) { yield return(statement); } var unpackValueArguments = new[] { context.Unpacker, context.UnpackingContextInUnpackValueMethods, context.IndexOfItem, context.ItemsCount } #if FEATURE_TAP .Concat(isAsync ? new[] { this.ReferCancellationToken(context, 2) } : NoConstructs).ToArray() #endif // FEATURE_TAP ; for (var i = 0; i < itemTypes.Count; i++) { var propertyName = SerializationTarget.GetTupleItemNameFromIndex(i); var unpackedItem = context.DefineUnpackedItemParameterInSetValueMethods(itemTypes[i]); var setUnpackValueOfMethodName = MethodNamePrefix.SetUnpackedValueOf + propertyName; var index = i; this.ExtractPrivateMethod( context, AdjustName(MethodNamePrefix.UnpackValue + propertyName, isAsync), false, // isStatic #if FEATURE_TAP isAsync ? TypeDefinition.TaskType : #endif // FEATURE_TAP TypeDefinition.VoidType, () => this.EmitUnpackItemValueStatement( context, itemTypes[index], this.MakeStringLiteral(context, propertyName), context.TupleItemNilImplication, null, // memberInfo itemSchemaList.Count == 0 ? null : itemSchemaList[index], context.Unpacker, context.UnpackingContextInUnpackValueMethods, context.IndexOfItem, context.ItemsCount, context.IsDeclaredMethod(setUnpackValueOfMethodName) ? this.EmitGetPrivateMethodDelegateExpression( context, context.GetDeclaredMethod(setUnpackValueOfMethodName) ) : this.ExtractPrivateMethod( context, setUnpackValueOfMethodName, false, // isStatic TypeDefinition.VoidType, () => unpackingContext.VariableType.TryGetRuntimeType() == typeof(DynamicUnpackingContext) ? this.EmitInvokeVoidMethod( context, context.UnpackingContextInSetValueMethods, Metadata._DynamicUnpackingContext.Set, this.MakeStringLiteral(context, propertyName), this.EmitBoxExpression( context, itemTypes[index], unpackedItem ) ) : this.EmitSetField( context, context.UnpackingContextInSetValueMethods, unpackingContext.VariableType, propertyName, unpackedItem ), context.UnpackingContextInSetValueMethods, unpackedItem ), isAsync ), unpackValueArguments ); } TConstruct currentTuple = null; for (int nest = tupleTypeList.Count - 1; nest >= 0; nest--) { var gets = Enumerable.Range(nest * 7, Math.Min(itemTypes.Count - nest * 7, 7)) .Select(i => unpackingContext.VariableType.TryGetRuntimeType() == typeof(DynamicUnpackingContext) ? this.EmitUnboxAnyExpression( context, itemTypes[i], this.EmitInvokeMethodExpression( context, context.UnpackingContextInCreateObjectFromContext, Metadata._DynamicUnpackingContext.Get, this.MakeStringLiteral(context, SerializationTarget.GetTupleItemNameFromIndex(i)) ) ) : this.EmitGetFieldExpression( context, context.UnpackingContextInCreateObjectFromContext, new FieldDefinition( unpackingContext.VariableType, SerializationTarget.GetTupleItemNameFromIndex(i), itemTypes[i] ) ) ); if (currentTuple != null) { gets = gets.Concat(new[] { currentTuple }); } currentTuple = this.EmitCreateNewObjectExpression( context, null, // Tuple is reference contextType. tupleTypeList[nest].GetConstructors().Single(), gets.ToArray() ); } #if DEBUG Contract.Assert(currentTuple != null); #endif unpackingContext.Factory = this.EmitNewPrivateMethodDelegateExpressionWithCreation( context, new MethodDefinition( MethodName.CreateObjectFromContext, null, null, true, // isStatic this.TargetType, unpackingContext.Type ), () => this.EmitRetrunStatement( context, currentTuple ), context.UnpackingContextInCreateObjectFromContext ); var unpackHelperArguments = new[] { context.Unpacker, unpackingContext.Variable, unpackingContext.Factory, this.EmitGetMemberNamesExpression(context), this.EmitGetActionsExpression(context, ActionType.UnpackFromArray, isAsync) } #if FEATURE_TAP .Concat(isAsync ? new[] { this.ReferCancellationToken(context, 2) } : NoConstructs).ToArray() #endif // FEATURE_TAP ; yield return (this.EmitRetrunStatement( context, this.EmitInvokeMethodExpression( context, null, new MethodDefinition( AdjustName(MethodName.UnpackFromArray, isAsync), new [] { unpackingContext.Type, this.TargetType }, TypeDefinition.UnpackHelpersType, true, // isStatic #if FEATURE_TAP isAsync ? typeof(Task <>).MakeGenericType(this.TargetType) : #endif // FEATURE_TAP this.TargetType, unpackHelperArguments.Select(a => a.ContextType).ToArray() ), unpackHelperArguments ) )); }
internal static MessagePackSerializer <T> CreateReflectionInternal <T>(SerializationContext context, Type concreteType, PolymorphismSchema schema) { if (concreteType.GetIsAbstract() || concreteType.GetIsInterface()) { // return null for polymoirphic provider. return(null); } var serializer = context.Serializers.Get <T>(context); if (serializer != null) { // For MessagePack.Create compatibility. // Required for built-in types. return(serializer); } ValidateType(typeof(T)); var traits = #if !UNITY typeof(T).GetCollectionTraits(CollectionTraitOptions.WithAddMethod, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes); #else typeof(T).GetCollectionTraits(CollectionTraitOptions.WithAddMethod | CollectionTraitOptions.WithCountPropertyGetter, context.CompatibilityOptions.AllowNonCollectionEnumerableTypes); #endif switch (traits.CollectionType) { case CollectionKind.Array: case CollectionKind.Map: { return (#if !UNITY ReflectionSerializerHelper.CreateCollectionSerializer <T>(context, concreteType, traits, (schema ?? PolymorphismSchema.Default))); #else Wrap <T>( context, ReflectionSerializerHelper.CreateCollectionSerializer <T>(context, concreteType, traits, (schema ?? PolymorphismSchema.Default)) ); #endif // !UNITY } default: { if (typeof(T).GetIsEnum()) { return(ReflectionSerializerHelper.CreateReflectionEnumMessagePackSerializer <T>(context)); } #if !NET35 && !UNITY if (TupleItems.IsTuple(typeof(T))) { return (new ReflectionTupleMessagePackSerializer <T>( context, (schema ?? PolymorphismSchema.Default).ChildSchemaList )); } #endif // !NET35 && !UNITY SerializationTarget.VerifyType(typeof(T)); var target = SerializationTarget.Prepare(context, typeof(T)); return(new ReflectionObjectMessagePackSerializer <T>(context, target, target.GetCapabilitiesForObject())); } } }
private IEnumerable <TConstruct> BuildTuplePackToCore(TContext context, IList <Type> itemTypes, IList <PolymorphismSchema> itemSchemaList, bool isAsync) { // Note: cardinality is put as array length by PackHelper. var depth = -1; var tupleTypeList = TupleItems.CreateTupleTypeList(itemTypes); var propertyInvocationChain = new List <PropertyInfo>(itemTypes.Count % 7 + 1); var packValueArguments = new[] { context.Packer, context.PackToTarget } #if FEATURE_TAP .Concat(isAsync ? new[] { this.ReferCancellationToken(context, 3) } : NoConstructs).ToArray() #endif // FEATURE_TAP ; for (int i = 0; i < itemTypes.Count; i++) { if (i % 7 == 0) { depth++; } for (int j = 0; j < depth; j++) { // .TRest.TRest ... var restProperty = tupleTypeList[j].GetProperty("Rest"); #if DEBUG Contract.Assert(restProperty != null); #endif propertyInvocationChain.Add(restProperty); } var itemNProperty = tupleTypeList[depth].GetProperty("Item" + ((i % 7) + 1)); propertyInvocationChain.Add(itemNProperty); #if DEBUG Contract.Assert( itemNProperty != null, tupleTypeList[depth].GetFullName() + "::Item" + ((i % 7) + 1) + " [ " + depth + " ] @ " + i ); #endif var count = i; DefinePrivateMethod( context, AdjustName(MethodNamePrefix.PackValue + SerializationTarget.GetTupleItemNameFromIndex(i), isAsync), false, // isStatic #if FEATURE_TAP isAsync ? TypeDefinition.TaskType : #endif // FEATURE_TAP TypeDefinition.VoidType, () => this.EmitSequentialStatements( context, TypeDefinition.VoidType, this.EmitPackTupleItemStatements( context, itemTypes[count], context.Packer, context.PackToTarget, propertyInvocationChain, itemSchemaList.Count == 0 ? null : itemSchemaList[count], isAsync ) ), packValueArguments ); propertyInvocationChain.Clear(); } var packHelperArguments = new Dictionary <string, TConstruct> { { "Packer", context.Packer }, { "Target", context.PackToTarget }, { "Operations", this.EmitGetActionsExpression(context, ActionType.PackToArray, isAsync) } }; #if FEATURE_TAP if (isAsync) { packHelperArguments.Add("CancellationToken", this.ReferCancellationToken(context, 3)); } #endif // FEATURE_TAP var packHelperParameterTypeDefinition = #if FEATURE_TAP isAsync ? typeof(PackToArrayAsyncParameters <>) : #endif // FEATURE_TAP typeof(PackToArrayParameters <>); var packHelperParameterType = TypeDefinition.GenericValueType(packHelperParameterTypeDefinition, this.TargetType); var packHelperMethod = new MethodDefinition( AdjustName(MethodName.PackToArray, isAsync), new [] { TypeDefinition.Object(this.TargetType) }, TypeDefinition.PackHelpersType, true, // isStatic #if FEATURE_TAP isAsync ? TypeDefinition.TaskType : #endif // FEATURE_TAP TypeDefinition.VoidType, packHelperParameterType ); var packHelperParameters = this.DeclareLocal(context, packHelperParameterType, "packHelperParameters"); yield return(packHelperParameters); foreach (var construct in this.CreatePackUnpackHelperArgumentInitialization(context, packHelperParameters, packHelperArguments)) { yield return(construct); } var methodInvocation = this.EmitInvokeMethodExpression( context, null, packHelperMethod, this.EmitMakeRef(context, packHelperParameters) ); if (isAsync) { // Wrap with return to return Task methodInvocation = this.EmitRetrunStatement(context, methodInvocation); } yield return(methodInvocation); }