/// <summary> /// Deserializes collection items with specified <see cref="Unpacker"/> and stores them to <paramref name="collection"/>. /// </summary> /// <param name="unpacker"><see cref="Unpacker"/> which unpacks values of resulting object tree. This value will not be <c>null</c>.</param> /// <param name="collection">Collection that the items to be stored. This value will not be <c>null</c>.</param> /// <exception cref="SerializationException"> /// Failed to deserialize object due to invalid unpacker state, stream content, or so. /// </exception> /// <exception cref="NotSupportedException"> /// The type of <paramref name="collection" /> is not a collection. /// </exception> protected internal virtual void UnpackToCore(Unpacker unpacker, object collection) { throw SerializationExceptions.NewUnpackToIsNotSupported(this._targetType, null); }
public static SerializationTarget Prepare(SerializationContext context, Type targetType) { var getters = GetTargetMembers(targetType).OrderBy(entry => entry.Contract.Id).ToArray(); if (getters.Length == 0) { throw new SerializationException(String.Format(CultureInfo.CurrentCulture, "Cannot serialize type '{0}' because it does not have any serializable fields nor properties.", targetType)); } bool?canDeserialize = null; var memberCandidates = getters.Where(entry => CheckTargetEligibility(entry.Member)).ToArray(); if (memberCandidates.Length == 0) { var deserializationConstructor = FindDeserializationConstructor(context, targetType, out canDeserialize); var complementedMembers = ComplementMembers(getters, context, targetType); var correspondingMemberNames = FindCorrespondingMemberNames(complementedMembers, deserializationConstructor); return (new SerializationTarget( complementedMembers, deserializationConstructor, correspondingMemberNames, canDeserialize )); } // Try to get default constructor. var constructor = targetType.GetConstructor(ReflectionAbstractions.EmptyTypes); if (constructor == null && !targetType.GetIsValueType()) { // Try to get deserialization constructor. var deserializationConstructor = FindDeserializationConstructor(context, targetType, out canDeserialize); if (deserializationConstructor == null && !context.CompatibilityOptions.AllowAsymmetricSerializer) { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructor(targetType); } constructor = deserializationConstructor; } else { // Let's prefer annotated constructor here. var markedConstructors = FindExplicitDeserializationConstructors(targetType.GetConstructors()); if (markedConstructors.Count == 1) { // For backward compatibility, no exceptions are thrown here even if mulitiple deserialization constructor attributes in the type // just use default constructor for it. constructor = markedConstructors[0]; } // OK, appropriate constructor and setters are found. canDeserialize = true; } // Because members' order is equal to declared order is NOT guaranteed, so explicit ordering is required. IList <SerializingMember> members; if (memberCandidates.All(item => item.Contract.Id == DataMemberContract.UnspecifiedId)) { // Alphabetical order. members = memberCandidates.OrderBy(item => item.Contract.Name).ToArray(); } else { // ID order. members = ComplementMembers(memberCandidates, context, targetType); } return (new SerializationTarget( members, constructor, FindCorrespondingMemberNames(members, constructor), canDeserialize )); }
//20150611 applibot modify end private static IList <SerializingMember> PrepareCore(SerializationContext context, Type targetType) { //20150611 applibot modify //var entries = GetTargetMembers( targetType ).OrderBy( item => item.Contract.Id ).ToArray(); var entries = GetTargetMembers(targetType).OrderBy(intDelegateForAOT_).ToArray(); if (entries.Length == 0) { throw SerializationExceptions.NewNoSerializableFieldsException(targetType); } //20150611 applibot modify //if ( entries.All( item => item.Contract.Id == DataMemberContract.UnspecifiedId ) ) if (entries.All(boolDelegateForAOT_)) { // Alphabetical order. //20150611 applibot modify //return entries.OrderBy( item => item.Contract.Name ).ToArray(); return(entries.OrderBy(nameDelegateForAOT_).ToArray()); } // ID order. #if DEBUG && !UNITY Contract.Assert(entries[0].Contract.Id >= 0); #endif // DEBUG && !UNITY if (context.CompatibilityOptions.OneBoundDataMemberOrder && entries[0].Contract.Id == 0) { throw new NotSupportedException("Cannot specify order value 0 on DataMemberAttribute when SerializationContext.CompatibilityOptions.OneBoundDataMemberOrder is set to true."); } //20150611 applibot modify int maxId = 0; foreach (SerializingMember item in entries) { if (maxId < item.Contract.Id) { maxId = item.Contract.Id; } } //var maxId = entries.Max( item => item.Contract.Id ); //var maxId = entries.Max( intDelegateForAOT_ ); var result = new List <SerializingMember>(maxId + 1); for (int source = 0, destination = context.CompatibilityOptions.OneBoundDataMemberOrder ? 1 : 0; source < entries.Length; source++, destination++) { #if DEBUG && !UNITY Contract.Assert(entries[source].Contract.Id >= 0); #endif // DEBUG && !UNITY if (entries[source].Contract.Id < destination) { throw new SerializationException(String.Format(CultureInfo.CurrentCulture, "The member ID '{0}' is duplicated in the '{1}' elementType.", entries[source].Contract.Id, targetType)); } while (entries[source].Contract.Id > destination) { result.Add(new SerializingMember()); destination++; } result.Add(entries[source]); } return(result); }
/// <summary> /// Retrieves a most appropriate constructor with <see cref="Int32"/> capacity parameter and <see cref="IEqualityComparer{T}"/> comparer parameter or both of them, >or default constructor of the <paramref name="instanceType"/>. /// </summary> /// <param name="instanceType">The target collection type to be instanciated.</param> /// <returns>A constructor of the <paramref name="instanceType"/>.</returns> internal static ConstructorInfo GetCollectionConstructor(Type instanceType) { const int noParameters = 0; const int withCapacity = 10; const int withComparer = 11; const int withComparerAndCapacity = 20; const int withCapacityAndComparer = 21; ConstructorInfo constructor = null; var currentScore = -1; foreach (var candidate in instanceType.GetConstructors()) { var parameters = candidate.GetParameters(); switch (parameters.Length) { case 0: { if (currentScore < noParameters) { constructor = candidate; currentScore = noParameters; } break; } case 1: { if (currentScore < withCapacity && parameters[0].ParameterType == typeof(int)) { constructor = candidate; currentScore = noParameters; } else if (currentScore < withComparer && IsIEqualityComparer(parameters[0].ParameterType)) { constructor = candidate; currentScore = noParameters; } break; } case 2: { if (currentScore < withCapacityAndComparer && parameters[0].ParameterType == typeof(int) && IsIEqualityComparer(parameters[1].ParameterType)) { constructor = candidate; currentScore = withCapacityAndComparer; } else if (currentScore < withComparerAndCapacity && parameters[1].ParameterType == typeof(int) && IsIEqualityComparer(parameters[0].ParameterType)) { constructor = candidate; currentScore = withComparerAndCapacity; } break; } } } if (constructor == null) { SerializationExceptions.ThrowTargetDoesNotHavePublicDefaultConstructorNorInitialCapacity(instanceType); } return(constructor); }
public static void UnpackMapTo(Unpacker unpacker, IDictionary dictionary) { #if DEBUG if (unpacker == null) { throw new ArgumentNullException("unpacker"); } if (dictionary == null) { throw new ArgumentNullException("dictionary"); } if (!unpacker.IsMapHeader) { throw SerializationExceptions.NewIsNotMapHeader(); } Contract.EndContractBlock(); #endif int count = GetItemsCount(unpacker); for (int i = 0; i < count; i++) { if (!unpacker.Read()) { throw SerializationExceptions.NewMissingItem(i); } MessagePackObject key; if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader) { key = _messagePackObjectSerializer.UnpackFrom(unpacker); } else { using (Unpacker subtreeUnpacker = unpacker.ReadSubtree()) { key = _messagePackObjectSerializer.UnpackFrom(subtreeUnpacker); } } if (!unpacker.Read()) { throw SerializationExceptions.NewMissingItem(i); } MessagePackObject value; if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader) { value = _messagePackObjectSerializer.UnpackFrom(unpacker); } else { using (Unpacker subtreeUnpacker = unpacker.ReadSubtree()) { value = _messagePackObjectSerializer.UnpackFrom(subtreeUnpacker); } } dictionary.Add(key, value); } }
public static void UnpackMapTo <TKey, TValue>(Unpacker unpacker, MessagePackSerializer <TKey> keySerializer, MessagePackSerializer <TValue> valueSerializer, IDictionary <TKey, TValue> dictionary) { if (unpacker == null) { SerializationExceptions.ThrowArgumentNullException("unpacker"); } if (keySerializer == null) { SerializationExceptions.ThrowArgumentNullException("keySerializer"); } if (valueSerializer == null) { SerializationExceptions.ThrowArgumentNullException("valueSerializer"); } if (dictionary == null) { SerializationExceptions.ThrowArgumentNullException("dictionary"); } #if ASSERT Contract.Assert(unpacker != null); Contract.Assert(keySerializer != null); Contract.Assert(valueSerializer != null); Contract.Assert(dictionary != null); #endif // ASSERT if (!unpacker.IsMapHeader) { SerializationExceptions.ThrowIsNotMapHeader(unpacker); } #if ASSERT Contract.EndContractBlock(); #endif // ASSERT int count = GetItemsCount(unpacker); for (int i = 0; i < count; i++) { if (!unpacker.Read()) { SerializationExceptions.ThrowMissingItem(i, unpacker); } TKey key; if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader) { key = keySerializer.UnpackFrom(unpacker); } else { using (Unpacker subtreeUnpacker = unpacker.ReadSubtree()) { key = keySerializer.UnpackFrom(subtreeUnpacker); } } if (!unpacker.Read()) { SerializationExceptions.ThrowMissingItem(i, unpacker); } TValue value; if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader) { value = valueSerializer.UnpackFrom(unpacker); } else { using (Unpacker subtreeUnpacker = unpacker.ReadSubtree()) { value = valueSerializer.UnpackFrom(subtreeUnpacker); } } dictionary.Add(key, value); } }
public static void UnpackCollectionTo <T, TDiscarded>(Unpacker unpacker, MessagePackSerializer <T> serializer, IEnumerable <T> collection, Func <T, TDiscarded> addition) { if (unpacker == null) { SerializationExceptions.ThrowArgumentNullException("unpacker"); } if (serializer == null) { SerializationExceptions.ThrowArgumentNullException("serializer"); } if (collection == null) { SerializationExceptions.ThrowArgumentNullException("collection"); } if (addition == null) { SerializationExceptions.ThrowArgumentNullException("addition"); } #if ASSERT Contract.Assert(unpacker != null); Contract.Assert(serializer != null); Contract.Assert(collection != null); Contract.Assert(addition != null); #endif // ASSERT if (!unpacker.IsArrayHeader) { SerializationExceptions.ThrowIsNotArrayHeader(unpacker); } #if ASSERT Contract.EndContractBlock(); #endif // ASSERT int count = GetItemsCount(unpacker); for (int i = 0; i < count; i++) { if (!unpacker.Read()) { SerializationExceptions.ThrowMissingItem(i, unpacker); } T item; if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader) { item = serializer.UnpackFrom(unpacker); } else { using (Unpacker subtreeUnpacker = unpacker.ReadSubtree()) { item = serializer.UnpackFrom(subtreeUnpacker); } } addition(item); } }
/// <summary> /// Deserializes collection items with specified <see cref="Unpacker"/> and stores them to <paramref name="collection"/>. /// </summary> /// <param name="unpacker"><see cref="Unpacker"/> which unpacks values of resulting object tree. This value will not be <c>null</c>.</param> /// <param name="collection">Collection that the items to be stored. This value will not be <c>null</c>.</param> /// <exception cref="SerializationException"> /// Failed to deserialize object due to invalid unpacker state, stream content, or so. /// </exception> /// <exception cref="NotSupportedException"> /// <typeparamref name="T"/> is not collection. /// </exception> protected internal virtual void UnpackToCore(Unpacker unpacker, T collection) { throw SerializationExceptions.NewUnpackToIsNotSupported(typeof(T), null); }
public static SerializationTarget Prepare(SerializationContext context, Type targetType) { VerifyCanSerializeTargetType(context, targetType); var getters = GetTargetMembers(targetType).OrderBy(entry => entry.Contract.Id).ToArray(); if (getters.Length == 0 && !typeof(IPackable).IsAssignableFrom(targetType) && !typeof(IUnpackable).IsAssignableFrom(targetType) #if FEATURE_TAP && (context.SerializerOptions.WithAsync && (!typeof(IAsyncPackable).IsAssignableFrom(targetType) && !typeof(IAsyncUnpackable).IsAssignableFrom(targetType) ) ) #endif // FEATURE_TAP ) { throw new SerializationException(String.Format(CultureInfo.CurrentCulture, "Cannot serialize type '{0}' because it does not have any serializable fields nor properties.", targetType)); } var memberCandidates = getters.Where(entry => CheckTargetEligibility(context, entry.Member)).ToArray(); if (memberCandidates.Length == 0) { ConstructorKind constructorKind; var deserializationConstructor = FindDeserializationConstructor(context, targetType, out constructorKind); var complementedMembers = ComplementMembers(getters, context, targetType); var correspondingMemberNames = FindCorrespondingMemberNames(complementedMembers, deserializationConstructor); return (new SerializationTarget( complementedMembers, deserializationConstructor, correspondingMemberNames, DetermineCanDeserialize(constructorKind, context, targetType, correspondingMemberNames, allowDefault: false) )); } else { bool? canDeserialize; ConstructorKind constructorKind; // Try to get default constructor. var constructor = targetType.GetConstructor(ReflectionAbstractions.EmptyTypes); if (constructor == null && !targetType.GetIsValueType()) { // Try to get deserialization constructor. var deserializationConstructor = FindDeserializationConstructor(context, targetType, out constructorKind); if (deserializationConstructor == null && !context.CompatibilityOptions.AllowAsymmetricSerializer) { throw SerializationExceptions.NewTargetDoesNotHavePublicDefaultConstructor(targetType); } constructor = deserializationConstructor; canDeserialize = null; } else { constructorKind = ConstructorKind.Default; // Let's prefer annotated constructor here. var markedConstructors = FindExplicitDeserializationConstructors(targetType.GetConstructors()); if (markedConstructors.Count == 1) { // For backward compatibility, no exceptions are thrown here even if mulitiple deserialization constructor attributes in the type // just use default constructor for it. constructor = markedConstructors[0]; constructorKind = ConstructorKind.Marked; } // OK, appropriate constructor and setters are found. canDeserialize = true; } if (constructor != null && constructor.GetParameters().Any()) { // Recalculate members because getter-only/readonly members should be included for constructor deserialization. memberCandidates = getters; } // Because members' order is equal to declared order is NOT guaranteed, so explicit ordering is required. IList <SerializingMember> members; if (memberCandidates.All(item => item.Contract.Id == DataMemberContract.UnspecifiedId)) { // Alphabetical order. members = memberCandidates.OrderBy(item => item.Contract.Name).ToArray(); } else { // ID order. members = ComplementMembers(memberCandidates, context, targetType); } var correspondingMemberNames = FindCorrespondingMemberNames(members, constructor); return (new SerializationTarget( members, constructor, correspondingMemberNames, canDeserialize ?? DetermineCanDeserialize(constructorKind, context, targetType, correspondingMemberNames, allowDefault: true) )); } }
public static void PackToMap <TObject>( ref PackToMapParameters <TObject> parameter ) { if (parameter.Packer == null) { SerializationExceptions.ThrowArgumentNullException("parameter", "Packer"); } if (parameter.Operations == null) { SerializationExceptions.ThrowArgumentNullException("parameter", "Operations"); } #if ASSERT Contract.Assert(parameter.Packer != null); Contract.Assert(parameter.Operations != null); #endif // ASSERT if (parameter.NullCheckers != null && parameter.SerializationContext != null && parameter.SerializationContext.DictionarySerlaizationOptions.OmitNullEntry) { #if ASSERT Contract.Assert(!SerializerDebugging.UseLegacyNullMapEntryHandling); #endif // ASSERT // Skipping causes the entries count header reducing, so count up null entries first. var nullCount = 0; foreach (var nullChecker in parameter.NullCheckers) { if (nullChecker.Value(parameter.Target)) { nullCount++; } } parameter.Packer.PackMapHeader(parameter.Operations.Count - nullCount); foreach (var operation in parameter.Operations) { Func <TObject, bool> nullChecker; if (parameter.NullCheckers.TryGetValue(operation.Key, out nullChecker)) { if (nullChecker(parameter.Target)) { continue; } } parameter.Packer.PackString(operation.Key); operation.Value(parameter.Packer, parameter.Target); } } else { parameter.Packer.PackMapHeader(parameter.Operations.Count); // Compatible path foreach (var operation in parameter.Operations) { parameter.Packer.PackString(operation.Key); operation.Value(parameter.Packer, parameter.Target); } } #pragma warning restore 618 }