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