Esempio n. 1
0
        public override object Get(SerializationContext context, object providerParameter)
        {
            var schema = (providerParameter ?? this._defaultSchema) as PolymorphismSchema;

            if (schema == null || schema.UseDefault || schema.TargetType != typeof(T))
            {
                // No schema is applied or this provider is used for container but the schema is only applied for keys/items.
                if (this._defaultSerializer == null)
                {
                    throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(T));
                }

                // Fallback.
                return(this._defaultSerializer);
            }

            if (schema.UseTypeEmbedding)
            {
                return(new TypeEmbedingPolymorphicMessagePackSerializer <T>(context, schema));
            }
            else
            {
                return(new KnownTypePolymorphicMessagePackSerializer <T>(context, schema));
            }
        }
Esempio n. 2
0
        public static void EmitConstruction(TracingILGenerator il, LocalBuilder target, Action <TracingILGenerator> initialCountLoadingEmitter)
        {
            Contract.Requires(il != null);
            Contract.Requires(target != null);

            // TODO: For collection, supports .ctor(IEnumerable<> other)

            if (target.LocalType.IsAbstract || target.LocalType.IsInterface)
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(target.LocalType);
            }

            if (target.LocalType.IsArray)
            {
                Contract.Assert(initialCountLoadingEmitter != null);
                initialCountLoadingEmitter(il);
                il.EmitNewarr(target.LocalType.GetElementType());
                il.EmitAnyStloc(target);
                return;
            }

            ConstructorInfo ctor = target.LocalType.GetConstructor(_ctor_Int32_ParameterTypes);

            if (ctor != null && initialCountLoadingEmitter != null && typeof(IEnumerable).IsAssignableFrom(target.LocalType))
            {
                if (target.LocalType.IsValueType)
                {
                    // Same as general method call
                    var capacity = il.DeclareLocal(typeof(int), "capacity");
                    initialCountLoadingEmitter(il);
                    il.EmitAnyStloc(capacity);
                    il.EmitAnyLdloca(target);
                    il.EmitAnyLdloc(capacity);
                    il.EmitCallConstructor(ctor);
                }
                else
                {
                    initialCountLoadingEmitter(il);
                    il.EmitNewobj(ctor);
                    il.EmitAnyStloc(target);
                }
                return;
            }

            if (target.LocalType.IsValueType)
            {
                // ValueType instance has been initialized by the runtime.
                return;
            }

            ctor = target.LocalType.GetConstructor(Type.EmptyTypes);
            if (ctor == null)
            {
                throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(target.LocalType);
            }

            il.EmitNewobj(ctor);
            il.EmitAnyStloc(target);
        }
Esempio n. 3
0
        public ListExpressionMessagePackSerializer(SerializationContext context, CollectionTraits traits)
            : base(context, traits)
        {
            Type type = typeof(T);

            if (type.GetIsAbstract())
            {
                type = context.DefaultCollectionTypes.GetConcreteType(typeof(T)) ?? type;
            }

            if (type.IsArray)
            {
                var capacityParameter = Expression.Parameter(typeof(int), "length");
                this._createInstanceWithCapacity =
                    Expression.Lambda <Func <int, T> >(
                        Expression.NewArrayBounds(type.GetElementType(), capacityParameter),
                        capacityParameter
                        ).Compile();
                this._createInstance = null;
            }
            else if (type.GetIsAbstract())
            {
                this._createInstance             = () => { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type); };
                this._createInstanceWithCapacity = null;
            }
            else
            {
                var constructor = ExpressionSerializerLogics.GetCollectionConstructor(context, type);
                if (constructor == null)
                {
                    this._createInstance             = () => { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(type); };
                    this._createInstanceWithCapacity = null;
                }
                else
                {
                    if (constructor.GetParameters().Length == 1)
                    {
                        this._createInstance = null;

                        var capacityParameter = Expression.Parameter(typeof(int), "parameter");
                        this._createInstanceWithCapacity =
                            Expression.Lambda <Func <int, T> >(
                                Expression.New(constructor, capacityParameter),
                                capacityParameter
                                ).Compile();
                    }
                    else
                    {
                        this._createInstanceWithCapacity = null;
                        this._createInstance             =
                            Expression.Lambda <Func <T> >(
                                Expression.New(constructor)
                                ).Compile();
                    }
                }
            }
        }
        public ListReflectionMessagePackSerializer(Type type, SerializationContext context, CollectionTraits traits)
            : base(type, context, traits)
        {
            if (type.GetIsAbstract())
            {
                type = context.DefaultCollectionTypes.GetConcreteType(type) ?? type;
            }

            if (type.IsArray)
            {
                var elementType = type.GetElementType();
                this._createInstanceWithCapacity = length =>
                {
                    return(Array.CreateInstance(elementType, length));
                };
                this._createInstance = null;
            }
            else if (type.GetIsAbstract())
            {
                this._createInstance             = () => { throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type); };
                this._createInstanceWithCapacity = null;
            }
            else
            {
                var constructor = ReflectionSerializerLogics.GetCollectionConstructor(context, type);
                if (constructor == null)
                {
                    this._createInstance             = () => { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(type); };
                    this._createInstanceWithCapacity = null;
                }
                else
                {
                    if (constructor.GetParameters().Length == 1)
                    {
                        this._createInstance = null;

                        this._createInstanceWithCapacity = length => constructor.Invoke(new object[] { length });
                    }
                    else
                    {
                        this._createInstanceWithCapacity = null;
                        this._createInstance             = () => constructor.Invoke(new object[0]);
                    }
                }
            }
        }
        public static void GetConcreteSerializer(
            SerializationContext context,
            PolymorphismSchema schema,
            Type abstractType,
            Type targetType,
            Type exampleType,
            out ICollectionInstanceFactory factory,
            out IMessagePackSingleObjectSerializer serializer
            )
        {
            if (abstractType == targetType)
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(abstractType);
            }

            serializer = context.GetSerializer(targetType, schema);
            factory    = serializer as ICollectionInstanceFactory;
            if (factory == null && (serializer as IPolymorphicDeserializer) == null)
            {
                throw SerializationExceptions.NewIncompatibleCollectionSerializer(abstractType, serializer.GetType(), exampleType);
            }
        }
        private void BuildCollectionUnpackFrom(TContext context, CollectionTraits traits)
        {
            this.EmitMethodPrologue(context, SerializerMethod.UnpackFromCore);

            TConstruct construct = null;

            try
            {
                Type instanceType;
                if (typeof(TObject).GetIsInterface() || typeof(TObject).GetIsAbstract())
                {
                    instanceType = context.SerializationContext.DefaultCollectionTypes.GetConcreteType(typeof(TObject));
                    if (instanceType == null)
                    {
                        throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(TObject));
                    }
                }
                else
                {
                    instanceType = typeof(TObject);
                }

                /*
                 *	if (!unpacker.IsArrayHeader)
                 *	{
                 *		throw SerializationExceptions.NewIsNotArrayHeader();
                 *	}
                 *	int capacity = ITEMS_COUNT(unpacker);
                 *	TCollection collection = new ...;
                 *	this.UnpackToCore(unpacker, array);
                 *	return collection;
                 */
                var collection =
                    this.DeclareLocal(
                        context,
                        instanceType,
                        "collection"
                        );
                var ctor = GetCollectionConstructor(instanceType);
                var collectionCapacity = this.EmitGetItemsCountExpression(context, context.Unpacker);

                construct =
                    this.EmitSequentialStatements(
                        context,
                        collection.ContextType,
                        this.EmitCheckIsArrayHeaderExpression(context, context.Unpacker),
                        collection,
                        traits.AddMethod == null
                                                ? this.EmitSequentialStatements(
                            context,
                            typeof(void),
                            this.EmitStoreVariableStatement(
                                context,
                                collection,
                                this.EmitCreateNewObjectExpression(
                                    context,
                                    collection,
                                    ctor,
                                    ctor.GetParameters().Length == 0
                                                                        ? NoConstructs
                                                                        : new[] { collectionCapacity }
                                    )
                                ),
                            this.EmitUnpackToSpecifiedCollection(context, instanceType.GetCollectionTraits(), context.Unpacker, collection)
                            ) : this.EmitUnpackCollectionWithUnpackToExpression(
                            context,
                            ctor,
                            collectionCapacity,
                            context.Unpacker,
                            collection
                            ),
                        this.EmitRetrunStatement(
                            context,
                            this.EmitLoadVariableExpression(context, collection)
                            )
                        );
            }
            finally
            {
                this.EmitMethodEpilogue(context, SerializerMethod.UnpackFromCore, construct);
            }
        }
        protected ObjectReflectionMessagePackSerializer(Type type, SerializationContext context, SerializingMember[] members)
            : base(type, (context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions)
        {
            if (type.GetIsAbstract() || type.GetIsInterface())
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(type);
            }

            this._createInstance = () => Activator.CreateInstance(type);

            //Expression.Lambda<Func<T>>(
            //    typeof(T).GetIsValueType()
            //        ? Expression.Default(typeof(T)) as Expression
            //        : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes))
            //    ).Compile();
            var isPackable   = typeof(IPackable).IsAssignableFrom(type);
            var isUnpackable = typeof(IUnpackable).IsAssignableFrom(type);

            if (isPackable && isUnpackable)
            {
                this._memberSerializers = null;
                this._indexMap          = null;
                this._isCollection      = null;
                this._nilImplications   = null;
                this._memberNames       = null;
            }
            else
            {
                this._memberSerializers =
                    members.Select(
                        m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray
                    (

                    );
                this._indexMap =
                    members
                    .Select((m, i) => new KeyValuePair <SerializingMember, int>(m, i))
                    .Where(kv => kv.Key.Member != null)
                    .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value);

                this._isCollection =
                    members.Select(
                        m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()).
                    Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray();

                // NilImplication validity check
                foreach (var member in members)
                {
                    switch (member.Contract.NilImplication)
                    {
                    case NilImplication.Null:
                    {
                        if (member.Member.GetMemberValueType().GetIsValueType() &&
                            Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)
                        {
                            throw SerializationExceptions.NewValueTypeCannotBeNull(
                                      member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType
                                      );
                        }

                        if (!member.Member.CanSetValue())
                        {
                            throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name);
                        }

                        break;
                    }
                    }
                }

                this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray();
                this._memberNames     = members.Select(m => m.Contract.Name).ToArray();
            }

            if (isPackable)
            {
                this._packToMessage = (target, packer, packingOptions) =>
                {
                    ((IPackable)target).PackToMessage(packer, packingOptions);
                    //typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single().Invoke(target, new object[] { packer, packingOptions });
                };
                this._memberGetters = null;
            }
            else
            {
                this._packToMessage = null;
                this._memberGetters =
                    members.Select <SerializingMember, Func <object, object> >(
                        m => m.Member == null ? (target => null)
                        : CreateMemberGetter(m)).ToArray();
            }

            if (isUnpackable)
            {
                this._unpackFromMessage = delegate(ref object target, Unpacker value)
                {
                    ((IUnpackable)target).UnpackFromMessage(value);
                };

                this._memberSetters = null;
            }
            else
            {
                this._unpackFromMessage = null;

                this._memberSetters =
                    members.Select(
                        m =>
                        m.Member == null
                        ? delegate(ref object target, object memberValue) { }
                :
                        m.Member.CanSetValue()
                        ? CreateMemberSetter(m)
                        : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member)
                        ? default(MemberSetter)
                        : ThrowGetOnlyMemberIsInvalid(m.Member)
                        ).ToArray();
            }
        }
        protected ObjectExpressionMessagePackSerializer(SerializationContext context, SerializingMember[] members)
            : base((context ?? SerializationContext.Default).CompatibilityOptions.PackerCompatibilityOptions)
        {
            if (typeof(T).GetIsAbstract() || typeof(T).GetIsInterface())
            {
                throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(T));
            }

            this._createInstance =
                Expression.Lambda <Func <T> >(
                    typeof(T).GetIsValueType()
                                                ? Expression.Default(typeof(T)) as Expression
                                                : Expression.New(typeof(T).GetConstructor(ReflectionAbstractions.EmptyTypes))
                    ).Compile();
            var isPackable   = typeof(IPackable).IsAssignableFrom(typeof(T));
            var isUnpackable = typeof(IUnpackable).IsAssignableFrom(typeof(T));

            var targetParameter = Expression.Parameter(typeof(T), "target");

            if (isPackable && isUnpackable)
            {
                this._memberSerializers = null;
                this._indexMap          = null;
                this._isCollection      = null;
                this._nilImplications   = null;
                this._memberNames       = null;
            }
            else
            {
                this._memberSerializers =
                    members.Select(
                        m => m.Member == null ? NullSerializer.Instance : context.GetSerializer(m.Member.GetMemberValueType())).ToArray
                    (

                    );
                this._indexMap =
                    members
                    .Zip(Enumerable.Range(0, members.Length), (m, i) => new KeyValuePair <SerializingMember, int>(m, i))
                    .Where(kv => kv.Key.Member != null)
                    .ToDictionary(kv => kv.Key.Contract.Name, kv => kv.Value);

                this._isCollection =
                    members.Select(
                        m => m.Member == null ? CollectionTraits.NotCollection : m.Member.GetMemberValueType().GetCollectionTraits()).
                    Select(t => t.CollectionType != CollectionKind.NotCollection).ToArray();

                // NilImplication validity check
                foreach (var member in members)
                {
                    switch (member.Contract.NilImplication)
                    {
                    case NilImplication.Null:
                    {
                        if (member.Member.GetMemberValueType().GetIsValueType() &&
                            Nullable.GetUnderlyingType(member.Member.GetMemberValueType()) == null)
                        {
                            throw SerializationExceptions.NewValueTypeCannotBeNull(
                                      member.Contract.Name, member.Member.GetMemberValueType(), member.Member.DeclaringType
                                      );
                        }

                        if (!member.Member.CanSetValue())
                        {
                            throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(member.Contract.Name);
                        }

                        break;
                    }
                    }
                }

                this._nilImplications = members.Select(m => m.Contract.NilImplication).ToArray();
                this._memberNames     = members.Select(m => m.Contract.Name).ToArray();
            }

            if (isPackable)
            {
                var packerParameter  = Expression.Parameter(typeof(Packer), "packer");
                var optionsParameter = Expression.Parameter(typeof(PackingOptions), "options");
                this._packToMessage =
                    Expression.Lambda <Action <T, Packer, PackingOptions> >(
                        Expression.Call(
                            targetParameter,
                            typeof(T).GetInterfaceMap(typeof(IPackable)).TargetMethods.Single(),
                            packerParameter,
                            optionsParameter
                            ),
                        targetParameter, packerParameter, optionsParameter
                        ).Compile();
                this._memberGetters = null;
            }
            else
            {
                this._packToMessage = null;
                this._memberGetters =
                    members.Select(
                        m =>
                        m.Member == null
                                                ? Expression.Lambda <Func <T, object> >(
                            Expression.Constant(null),
                            targetParameter
                            ).Compile()
                                                : CreateMemberGetter(targetParameter, m)
                        ).ToArray();
            }

            var refTargetParameter = Expression.Parameter(typeof(T).MakeByRefType(), "target");

            if (isUnpackable)
            {
                var unpackerParameter = Expression.Parameter(typeof(Unpacker), "unpacker");
                this._unpackFromMessage =
                    Expression.Lambda <UnpackFromMessageInvocation>(
                        Expression.Call(
                            refTargetParameter,
                            typeof(T).GetInterfaceMap(typeof(IUnpackable)).TargetMethods.Single(),
                            unpackerParameter
                            ),
                        refTargetParameter, unpackerParameter
                        ).Compile();
                this._memberSetters = null;
            }
            else
            {
                this._unpackFromMessage = null;

                var valueParameter = Expression.Parameter(typeof(object), "value");
                this._memberSetters =
                    members.Select(
                        m =>
                        m.Member == null
                                                ? Expression.Lambda <MemberSetter>(
                            Expression.Empty(),
                            refTargetParameter,
                            valueParameter
                            ).Compile()
                                                : m.Member.CanSetValue()
                                                ? Expression.Lambda <MemberSetter>(
                            Expression.Assign(
                                Expression.PropertyOrField(
                                    refTargetParameter,
                                    m.Member.Name
                                    ),
                                Expression.Call(
                                    Metadata._UnpackHelpers.ConvertWithEnsuringNotNull_1Method.MakeGenericMethod(m.Member.GetMemberValueType()),
                                    valueParameter,
                                    Expression.Constant(m.Member.Name),
                                    Expression.Call(                                     // Using RuntimeTypeHandle to avoid WinRT expression tree issue.
                                        null,
                                        Metadata._Type.GetTypeFromHandle,
                                        Expression.Constant(m.Member.DeclaringType.TypeHandle)
                                        )
                                    )
                                ),
                            refTargetParameter,
                            valueParameter
                            ).Compile()
                                                : UnpackHelpers.IsReadOnlyAppendableCollectionMember(m.Member)
                                                ? default(MemberSetter)
                                                : ThrowGetOnlyMemberIsInvalid(m.Member)
                        ).ToArray();
            }
        }
        private void BuildMapUnpackFrom(TContext context)
        {
            this.EmitMethodPrologue(context, SerializerMethod.UnpackFromCore);
            TConstruct construct = null;

            try
            {
                Type instanceType;
                if (typeof(TObject).GetIsInterface() || typeof(TObject).GetIsAbstract())
                {
                    instanceType = context.SerializationContext.DefaultCollectionTypes.GetConcreteType(typeof(TObject));
                    if (instanceType == null)
                    {
                        throw SerializationExceptions.NewNotSupportedBecauseCannotInstanciateAbstractType(typeof(TObject));
                    }
                }
                else
                {
                    instanceType = typeof(TObject);
                }

                /*
                 *	if (!unpacker.IsMapHeader)
                 *	{
                 *		throw SerializationExceptions.NewIsNotMapHeader();
                 *	}
                 *	int capacity = ITEMS_COUNT(unpacker);
                 *
                 *	TDictionary<TKey, TValue> dictionary = new ...;
                 *	this.UnpackToCore(unpacker, dictionary);
                 *	return dictionary;
                 */
                var collection =
                    this.DeclareLocal(
                        context,
                        typeof(TObject),
                        "collection"
                        );

                construct =
                    this.EmitSequentialStatements(
                        context,
                        typeof(TObject),
                        this.EmitCheckIsMapHeaderExpression(context, context.Unpacker),
                        collection,
                        this.EmitUnpackCollectionWithUnpackToExpression(
                            context,
                            GetCollectionConstructor(instanceType),
                            this.EmitGetItemsCountExpression(context, context.Unpacker),
                            context.Unpacker,
                            collection
                            ),
                        this.EmitRetrunStatement(
                            context,
                            this.EmitLoadVariableExpression(context, collection)
                            )
                        );
            }
            finally
            {
                this.EmitMethodEpilogue(context, SerializerMethod.UnpackFromCore, construct);
            }
        }