Esempio n. 1
0
        private void BuildTupleSerializer(TContext context, IList <PolymorphismSchema> itemSchemaList)
        {
            var itemTypes = TupleItems.GetTupleItemTypes(typeof(TObject));

            this.BuildTuplePackTo(context, itemTypes, itemSchemaList);
            this.BuildTupleUnpackFrom(context, itemTypes, itemSchemaList);
        }
Esempio n. 2
0
        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();
        }
Esempio n. 8
0
        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");
            }
        }
Esempio n. 10
0
        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);
        }
Esempio n. 14
0
        /// <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();
        }
Esempio n. 17
0
        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();
            }
        }
Esempio n. 18
0
        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) })
                     ));
        }
Esempio n. 20
0
        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
                         )
                     ));
        }
Esempio n. 21
0
        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()));
            }
            }
        }
Esempio n. 22
0
        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);
        }