Esempio n. 1
0
        private void HandleNilImplication(ref T instance, int index)
        {
            switch (this._nilImplications[index])
            {
            case NilImplication.Null:
            {
                if (this._memberSetters[index] == null)
                {
                    throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(this._memberNames[index]);
                }

                this._memberSetters[index](ref instance, null);
                break;
            }

            case NilImplication.MemberDefault:
            {
                break;
            }

            case NilImplication.Prohibit:
            {
                throw SerializationExceptions.NewNullIsProhibited(this._memberNames[index]);
            }
            }
        }
        private T UnpackMemberValue(T objectGraph, Unpacker unpacker, int itemsCount, ref int unpacked, int index, int unpackerOffset)
        {
            object nullable = null;
            var    setter   = this._setters[index];

            if (unpacked < itemsCount)
            {
                if (!unpacker.Read())
                {
                    throw SerializationExceptions.NewMissingItem(unpackerOffset);
                }

                if (!unpacker.LastReadData.IsNil)
                {
                    if (setter != null)
                    {
                        if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader)
                        {
                            nullable = this._serializers[index].UnpackFrom(unpacker);
                        }
                        else
                        {
                            using (Unpacker subtreeUnpacker = unpacker.ReadSubtree())
                            {
                                nullable = this._serializers[index].UnpackFrom(subtreeUnpacker);
                            }
                        }
                    }
                    else if (this._getters[index] != null)                         // null getter supposes undeclared member (should be treated as nil)
                    {
                        var collection = this._getters[index](objectGraph);
                        if (collection == null)
                        {
                            throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(this._contracts[index].Name);
                        }
                        using (Unpacker subtreeUnpacker = unpacker.ReadSubtree())
                        {
                            this._serializers[index].UnpackTo(subtreeUnpacker, collection);
                        }
                    }
                }
            }

            if (setter != null)
            {
                if (nullable == null)
                {
                    ReflectionNilImplicationHandler.Instance.OnUnpacked(
                        new ReflectionSerializerNilImplicationHandlerOnUnpackedParameter(
                            this._memberInfos[index].GetMemberValueType(),
                            value => SetMemverValue(objectGraph, setter, value),
                            this._contracts[index].Name,
                            this._memberInfos[index].DeclaringType
                            ),
                        this._contracts[index].NilImplication
                        )(null);
                }
                else
                {
                    objectGraph = SetMemverValue(objectGraph, setter, nullable);
                }
            }

            unpacked++;

            return(objectGraph);
        }
        private async Task UnpackAndAddCollectionItemAsync(object objectGraph, Unpacker unpacker, int index, CancellationToken cancellationToken)
        {
            var destination = this._getters[index](objectGraph);

            if (destination == null)
            {
                throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(this._contracts[index].Name);
            }

            var traits = destination.GetType().GetCollectionTraits(CollectionTraitOptions.WithAddMethod, this.OwnerContext.CompatibilityOptions.AllowNonCollectionEnumerableTypes);

            if (traits.AddMethod == null)
            {
                throw SerializationExceptions.NewUnpackToIsNotSupported(destination.GetType(), null);
            }

            var source = await this._serializers[index].UnpackFromAsync(unpacker, cancellationToken).ConfigureAwait(false) as IEnumerable;

            if (source != null)
            {
                switch (traits.DetailedCollectionType)
                {
                case CollectionDetailedKind.GenericDictionary:
                    {
                        // item should be KeyValuePair<TKey, TValue>
                        var arguments = new object[2];
                        var key       = default(PropertyInfo);
                        var value     = default(PropertyInfo);
                        foreach (var item in source)
                        {
                            if (key == null)
                            {
                                key   = item.GetType().GetProperty("Key");
                                value = item.GetType().GetProperty("Value");
                            }

                            arguments[0] = key.GetValue(item, null);
                            arguments[1] = value.GetValue(item, null);
                            traits.AddMethod.InvokePreservingExceptionType(destination, arguments);
                        }
                        break;
                    }

                case CollectionDetailedKind.NonGenericDictionary:
                    {
                        // item should be DictionaryEntry
                        var arguments = new object[2];
                        foreach (var item in source)
                        {
                            arguments[0] = ReflectionSerializerHelper.DictionaryEntryKeyProperty.GetValue(item, null);
                            arguments[1] = ReflectionSerializerHelper.DictionaryEntryValueProperty.GetValue(item, null);
                            traits.AddMethod.InvokePreservingExceptionType(destination, arguments);
                        }
                        break;
                    }

                default:
                    {
                        var arguments = new object[1];
                        foreach (var item in source)
                        {
                            arguments[0] = item;
                            traits.AddMethod.InvokePreservingExceptionType(destination, arguments);
                        }
                        break;
                    }
                }
            }
        }         // UnpackAndAddCollectionItemAsync
Esempio n. 4
0
        private void UnpackAndAddCollectionItem(object objectGraph, Unpacker unpacker, int index)
        {
            var destination = this._getters[index](objectGraph);

            if (destination == null)
            {
                throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(this._contracts[index].Name);
            }

            var traits = destination.GetType().GetCollectionTraits();

            if (traits.AddMethod == null)
            {
                throw SerializationExceptions.NewUnpackToIsNotSupported(destination.GetType(), null);
            }

            var source = this._serializers[index].UnpackFrom(unpacker) as IEnumerable;

            if (source != null)
            {
                switch (traits.DetailedCollectionType)
                {
                case CollectionDetailedKind.GenericDictionary:
                    {
                        // item should be KeyValuePair<TKey, TValue>
                        var arguments = new object[2];
                        var key       = default(PropertyInfo);
                        var value     = default(PropertyInfo);
                        foreach (var item in source)
                        {
                            if (key == null)
                            {
                                key   = item.GetType().GetProperty("Key");
                                value = item.GetType().GetProperty("Value");
                            }

                            arguments[0] = key.GetValue(item, null);
                            arguments[1] = value.GetValue(item, null);
                            traits.AddMethod.InvokePreservingExceptionType(destination, arguments);
                        }
                        break;
                    }

                case CollectionDetailedKind.NonGenericDictionary:
                    {
                        // item should be DictionaryEntry
                        var arguments = new object[2];
                        foreach (var item in source)
                        {
                            arguments[0] = DictionaryEntryKeyProperty.GetValue(item, null);
                            arguments[1] = DictionaryEntryValueProperty.GetValue(item, null);
                            traits.AddMethod.InvokePreservingExceptionType(destination, arguments);
                        }
                        break;
                    }

                default:
                    {
                        var arguments = new object[1];
                        foreach (var item in source)
                        {
                            arguments[0] = item;
                            traits.AddMethod.InvokePreservingExceptionType(destination, arguments);
                        }
                        break;
                    }
                }
            }
        }
        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();
            }
        }
Esempio n. 6
0
        /// <summary>
        ///		Emits the nil implication.
        /// </summary>
        /// <param name="il">The il generator.</param>
        /// <param name="unpackerArgumentIndex">Index of the unpacker argument.</param>
        /// <param name="member">Metadata of the serializing member.</param>
        /// <param name="endOfDeserialization">The label to the end of deserialization.</param>
        /// <param name="localHolder">The <see cref="LocalVariableHolder"/> which holds shared local variable information.</param>
        public static void EmitNilImplication(
            TracingILGenerator il,
            int unpackerArgumentIndex,
            SerializingMember member,
            Label endOfDeserialization,
            LocalVariableHolder localHolder
            )
        {
            switch (member.Contract.NilImplication)
            {
            case NilImplication.MemberDefault:
            {
                // TODO: This should be empty for extra items.

                /*
                 * if( unpacker.Data.Value.IsNil )
                 * {
                 *		// Skip current.
                 *		goto END_OF_DESERIALIZATION;
                 * }
                 */
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(Metadata._Unpacker.LastReadData);
                var data = localHolder.UnpackedData;
                il.EmitAnyStloc(data);
                il.EmitAnyLdloca(data);
                il.EmitGetProperty(Metadata._MessagePackObject.IsNil);
                il.EmitBrtrue(endOfDeserialization);

                break;
            }

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

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

                /*
                 * if( unpacker.Data.Value.IsNil )
                 * {
                 *		throw SerializationEceptions.NewProhibitNullException( "..." );
                 * }
                 */
                il.EmitAnyLdarg(unpackerArgumentIndex);
                il.EmitGetProperty(Metadata._Unpacker.LastReadData);
                var data = localHolder.UnpackedData;
                il.EmitAnyStloc(data);
                il.EmitAnyLdloca(data);
                il.EmitGetProperty(Metadata._MessagePackObject.IsNil);
                var endIf0 = il.DefineLabel("END_IF0");
                il.EmitBrfalse_S(endIf0);
                il.EmitLdstr(member.Contract.Name);
                il.EmitAnyCall(SerializationExceptions.NewNullIsProhibitedMethod);
                il.EmitThrow();
                il.MarkLabel(endIf0);

                break;
            }
            }
        }
        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();
            }
        }
Esempio n. 8
0
        private void UnpackFromMap(Unpacker unpacker, ref T instance)
        {
            while (unpacker.Read())
            {
                var memberName = GetMemberName(unpacker);
                int index;
                if (!this._indexMap.TryGetValue(memberName, out index))
                {
                    // Drains unused value.
                    if (!unpacker.Read())
                    {
                        throw SerializationExceptions.NewUnexpectedEndOfStream();
                    }

                    // TODO: unknown member handling.

                    continue;
                }

                // Fetches value
                if (!unpacker.Read())
                {
                    throw SerializationExceptions.NewUnexpectedEndOfStream();
                }

                if (unpacker.Data.Value.IsNil)
                {
                    switch (this._nilImplications[index])
                    {
                    case NilImplication.Null:
                    {
                        if (this._memberSetters[index] == null)
                        {
                            throw SerializationExceptions.NewReadOnlyMemberItemsMustNotBeNull(this._memberNames[index]);
                        }

                        this._memberSetters[index](ref instance, null);
                        continue;
                    }

                    case NilImplication.MemberDefault:
                    {
                        continue;
                    }

                    case NilImplication.Prohibit:
                    {
                        throw SerializationExceptions.NewNullIsProhibited(this._memberNames[index]);
                    }
                    }
                }

                if (unpacker.IsArrayHeader || unpacker.IsMapHeader)
                {
                    using (var subtreeUnpacker = unpacker.ReadSubtree())
                    {
                        this.UnpackMemberInMap(subtreeUnpacker, ref instance, index);
                    }
                }
                else
                {
                    this.UnpackMemberInMap(unpacker, ref instance, index);
                }
            }
        }