public void ReturnsCorrectFields() { var serializationManager = new SerializationManager(); var fieldsToSerialize = serializationManager.GetFieldsToSerialize(typeof(TestModel)).ToArray(); Assert.AreEqual(1, fieldsToSerialize.Length); Assert.AreEqual("_includedField", fieldsToSerialize[0]); }
public void ReturnsCorrectProperties() { var serializationManager = new SerializationManager(); var propertiesToSerialize = serializationManager.GetRegularPropertiesToSerialize(typeof(TestModel)).ToArray(); Assert.AreEqual(1, propertiesToSerialize.Length); Assert.AreEqual("IncludedRegularProperty", propertiesToSerialize[0].Key); }
public void ReturnsRightModifiersInRightOrderForInheritedClasses() { var serializationManager = new SerializationManager(); var modifiers = serializationManager.GetSerializerModifiers(typeof(TestModels.ModelC)); Assert.AreEqual(3, modifiers.Length); Assert.AreEqual(typeof(TestModels.ModelASerializerModifier), modifiers[0].GetType()); Assert.AreEqual(typeof(TestModels.ModelBSerializerModifier), modifiers[1].GetType()); Assert.AreEqual(typeof(TestModels.ModelCSerializerModifier), modifiers[2].GetType()); }
public void ReturnsCorrectValue() { var serializationManager = new SerializationManager(); var fields = serializationManager.GetFields(typeof(TestModel)).ToArray(); Assert.AreEqual(1, fields.Length); Assert.AreEqual("_includedField", fields[0].Key); Assert.AreEqual(SerializationMemberGroup.Field, fields[0].Value.MemberGroup); }
public void ReturnsCorrectValue() { var serializationManager = new SerializationManager(); var properties = serializationManager.GetRegularProperties(typeof(TestModel)).ToArray(); Assert.AreEqual(1, properties.Length); Assert.AreEqual("IncludedRegularProperty", properties[0].Key); Assert.AreEqual(SerializationMemberGroup.RegularProperty, properties[0].Value.MemberGroup); }
public void ReturnsCorrectValue() { var serializationManager = new SerializationManager(); var properties = serializationManager.GetCatelProperties(typeof(TestModel)).ToArray(); Assert.AreEqual(3, properties.Length); Assert.AreEqual("IncludedCatelProperty", properties[0].Key); Assert.AreEqual(SerializationMemberGroup.CatelProperty, properties[0].Value.MemberGroup); Assert.AreEqual("ExcludedCatelProperty", properties[1].Key); Assert.AreEqual(SerializationMemberGroup.CatelProperty, properties[1].Value.MemberGroup); Assert.AreEqual("ExcludedProtectedCatelProperty", properties[2].Key); Assert.AreEqual(SerializationMemberGroup.CatelProperty, properties[2].Value.MemberGroup); }
public void SerializesModelsWithParsableObjectsAndSerializerModifierNotUsingParse() { var originalObject = new TestModelWithParsableMembersWithoutAttributes(); originalObject.Vector = new Vector(1, 2, 3); var serializationManager = new SerializationManager(); serializationManager.AddSerializerModifier<TestModelWithParsableMembersWithoutAttributes, TestModelWithParsableMembersNotUsingParseSerializerModifier>(); TestSerializationOnAllSerializers((serializer, config, description) => { var clonedObject = SerializationTestHelper.SerializeAndDeserialize(originalObject, serializer, config); Assert.IsFalse(clonedObject.Vector.UsedParse); Assert.AreEqual(originalObject.Vector.X, clonedObject.Vector.X, description); Assert.AreEqual(originalObject.Vector.Y, clonedObject.Vector.Y, description); Assert.AreEqual(originalObject.Vector.Z, clonedObject.Vector.Z, description); }, serializationManager: serializationManager); }
/// <summary> /// Gets the serializable members for the specified model. /// </summary> /// <param name="context">The serialization context.</param> /// <param name="model">The model.</param> /// <param name="membersToIgnore">The members to ignore.</param> /// <returns>The list of members to serialize.</returns> /// <exception cref="ArgumentNullException">The <paramref name="model"/> is <c>null</c>.</exception> public virtual List <MemberValue> GetSerializableMembers(ISerializationContext <TSerializationContextInfo> context, object model, params string[] membersToIgnore) { Argument.IsNotNull("model", model); var listToSerialize = new List <MemberValue>(); var membersToIgnoreHashSet = new HashSet <string>(membersToIgnore); var modelType = model.GetType(); // If a basic type, we need to directly deserialize as member and replace the context model if (ShouldExternalSerializerHandleMember(context.ModelType)) { listToSerialize.Add(new MemberValue(SerializationMemberGroup.SimpleRootObject, modelType, modelType, RootObjectName, RootObjectName, model)); return(listToSerialize); } if (ShouldSerializeAsDictionary(modelType)) { listToSerialize.Add(new MemberValue(SerializationMemberGroup.Dictionary, modelType, modelType, CollectionName, CollectionName, model)); return(listToSerialize); } if (ShouldSerializeAsCollection(modelType)) { listToSerialize.Add(new MemberValue(SerializationMemberGroup.Collection, modelType, modelType, CollectionName, CollectionName, model)); return(listToSerialize); } if (modelType == typeof(SerializableKeyValuePair)) { var keyValuePair = (SerializableKeyValuePair)model; var keyType = typeof(object); var valueType = typeof(object); // Search max 2 levels deep, if not found, then we failed var parentDictionary = context.FindParentType(x => x.IsDictionary(), 2); if (parentDictionary != null) { var genericTypeDefinition = parentDictionary.GetGenericArgumentsEx(); keyType = genericTypeDefinition[0]; valueType = genericTypeDefinition[1]; } listToSerialize.Add(new MemberValue(SerializationMemberGroup.RegularProperty, modelType, keyType, "Key", "Key", keyValuePair.Key)); listToSerialize.Add(new MemberValue(SerializationMemberGroup.RegularProperty, modelType, valueType, "Value", "Value", keyValuePair.Value)); return(listToSerialize); } var modelInfo = _serializationModelCache.GetFromCacheOrFetch(modelType, () => { var catelProperties = SerializationManager.GetCatelPropertiesToSerialize(modelType); var fields = SerializationManager.GetFieldsToSerialize(modelType); var properties = SerializationManager.GetRegularPropertiesToSerialize(modelType); return(new SerializationModelInfo(modelType, catelProperties, fields, properties)); }); var members = new List <MemberMetadata>(); members.AddRange(modelInfo.CatelPropertiesByName.Values); members.AddRange(modelInfo.PropertiesByName.Values); members.AddRange(modelInfo.FieldsByName.Values); foreach (var memberMetadata in members) { var memberName = memberMetadata.MemberName; if (membersToIgnoreHashSet.Contains(memberName) || ShouldIgnoreMember(model, memberName)) { Log.Debug("Member '{0}' is being ignored for serialization", memberName); continue; } var memberValue = ObjectAdapter.GetMemberValue(model, memberName, modelInfo); if (memberValue != null) { listToSerialize.Add(memberValue); } } return(listToSerialize); }
public void ReturnsCorrectValue() { var serializationManager = new SerializationManager(); var fields = serializationManager.GetFieldNames(typeof(TestModel)).ToArray(); Assert.AreEqual(2, fields.Length); Assert.AreEqual("_excludedField", fields[0]); Assert.AreEqual("_includedField", fields[1]); }
public void ReturnsCorrectValue() { var serializationManager = new SerializationManager(); var properties = serializationManager.GetRegularPropertyNames(typeof(TestModel)).ToArray(); Assert.AreEqual(2, properties.Length); Assert.AreEqual("ExcludedRegularProperty", properties[0]); Assert.AreEqual("IncludedRegularProperty", properties[1]); }
public void ReturnsCorrectValue() { var serializationManager = new SerializationManager(); var properties = serializationManager.GetCatelPropertyNames(typeof(TestModel)).ToArray(); Assert.AreEqual(4, properties.Length); Assert.AreEqual("DateTimeProperty", properties[0]); Assert.AreEqual("IncludedCatelProperty", properties[1]); Assert.AreEqual("ExcludedCatelProperty", properties[2]); Assert.AreEqual("ExcludedProtectedCatelProperty", properties[3]); }
/// <summary> /// Deserializes the members. /// </summary> /// <param name="context">The context.</param> /// <returns>The deserialized list of member values.</returns> protected virtual List <MemberValue> DeserializeMembers(ISerializationContext <TSerializationContextInfo> context) { ApiCop.UpdateRule <InitializationApiCopRule>("SerializerBase.WarmupAtStartup", x => x.SetInitializationMode(InitializationMode.Lazy, GetType().GetSafeFullName(false))); var deserializedMemberValues = new List <MemberValue>(); var serializerModifiers = SerializationManager.GetSerializerModifiers(context.ModelType).Reverse(); var membersToDeserialize = GetSerializableMembers(context, context.Model); foreach (var member in membersToDeserialize) { var memberSerializationEventArgs = new MemberSerializationEventArgs(context, member); DeserializingMember.SafeInvoke(this, memberSerializationEventArgs); BeforeDeserializeMember(context, member); var serializationObject = DeserializeMember(context, member); if (serializationObject.IsSuccessful) { // Note that we need to sync the member values every time var memberValue = new MemberValue(member.MemberGroup, member.ModelType, member.MemberType, member.Name, member.NameForSerialization, serializationObject.MemberValue); if (memberValue.MemberGroup == SerializationMemberGroup.Dictionary) { var targetDictionary = TypeFactory.CreateInstance(member.MemberType) as IDictionary; if (targetDictionary == null) { throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a dictionary, but target model cannot be updated because it does not implement IDictionary", context.ModelTypeName); } var enumerable = memberValue.Value as List <SerializableKeyValuePair>; if (enumerable != null) { foreach (var item in enumerable) { targetDictionary.Add(item.Key, item.Value); } } else { var sourceDictionary = memberValue.Value as IDictionary; if (sourceDictionary != null) { foreach (var key in sourceDictionary.Keys) { targetDictionary.Add(key, sourceDictionary[key]); } } } member.Value = targetDictionary; } else if (memberValue.MemberGroup == SerializationMemberGroup.Collection) { var sourceCollection = memberValue.Value as IEnumerable; if (member.MemberType.IsArrayEx()) { var elementType = member.MemberType.GetElementTypeEx(); member.Value = sourceCollection.ToArray(elementType); } else { var targetCollection = TypeFactory.CreateInstance(member.MemberType) as IList; if (targetCollection == null) { throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a collection, but target model cannot be updated because it does not implement IList", context.ModelTypeName); } if (sourceCollection != null) { foreach (var item in sourceCollection) { targetCollection.Add(item); } } member.Value = targetCollection; } } else { member.Value = memberValue.Value; } deserializedMemberValues.Add(memberValue); foreach (var serializerModifier in serializerModifiers) { serializerModifier.DeserializeMember(context, member); memberValue.Value = member.Value; } AfterDeserializeMember(context, member); memberValue.Value = member.Value; DeserializedMember.SafeInvoke(this, memberSerializationEventArgs); memberValue.Value = member.Value; } } if (deserializedMemberValues.Count > 0) { var firstMember = deserializedMemberValues[0]; if (firstMember.MemberGroup == SerializationMemberGroup.SimpleRootObject) { // Completely replace root object (this is a basic (non-reference) type) context.Model = firstMember.Value; } else if (firstMember.MemberGroup == SerializationMemberGroup.Dictionary) { var targetDictionary = context.Model as IDictionary; if (targetDictionary == null) { throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a dictionary, but target model cannot be updated because it does not implement IDictionary", context.ModelTypeName); } targetDictionary.Clear(); var sourceDictionary = firstMember.Value as IDictionary; if (sourceDictionary != null) { foreach (var key in sourceDictionary.Keys) { targetDictionary.Add(key, sourceDictionary[key]); } } } else if (firstMember.MemberGroup == SerializationMemberGroup.Collection) { if (context.ModelType.IsArrayEx()) { context.Model = firstMember.Value; } else { var targetCollection = context.Model as IList; if (targetCollection == null) { throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a collection, but target model cannot be updated because it does not implement IList", context.ModelTypeName); } targetCollection.Clear(); var sourceCollection = firstMember.Value as IEnumerable; if (sourceCollection != null) { foreach (var item in sourceCollection) { targetCollection.Add(item); } } } } else { PopulateModel(context.Model, deserializedMemberValues.ToArray()); } } return(deserializedMemberValues); }
/// <summary> /// Returns whether the member value should be serialized using <c>ToString(IFormatProvider)</c> and deserialized using <c>Parse(string, IFormatProvider)</c>. /// </summary> /// <param name="memberValue">The member value.</param> /// <param name="checkActualMemberType">if set to <c>true</c>, check the actual member type.</param> /// <returns> /// <c>true</c> if the member should be serialized using parse. /// </returns> protected virtual bool ShouldSerializeUsingParseAndToString(MemberValue memberValue, bool checkActualMemberType) { var cacheKey = $"{memberValue.ModelTypeName}|{memberValue.Name}|{checkActualMemberType}"; return(_shouldSerializeUsingParseCache.GetFromCacheOrFetch(cacheKey, () => { var serializerModifiers = SerializationManager.GetSerializerModifiers(memberValue.ModelType); var useParseAndToString = false; var fieldInfo = memberValue.ModelType.GetFieldEx(memberValue.Name); if (fieldInfo != null) { useParseAndToString = fieldInfo.IsDecoratedWithAttribute <SerializeUsingParseAndToStringAttribute>(); } if (!useParseAndToString) { var propertyInfo = memberValue.ModelType.GetPropertyEx(memberValue.Name); if (propertyInfo != null) { useParseAndToString = propertyInfo.IsDecoratedWithAttribute <SerializeUsingParseAndToStringAttribute>(); } } // Note: serializer modifiers can always win foreach (var serializerModifier in serializerModifiers) { var value = serializerModifier.ShouldSerializeMemberUsingParse(memberValue); if (value.HasValue) { if (!value.Value) { return false; } // At least 1 serializer modifier wants this to be using parse and tostring useParseAndToString = true; } } if (!useParseAndToString) { return false; } var memberType = checkActualMemberType ? memberValue.ActualMemberType : memberValue.MemberType; if (memberType is null) { memberType = memberValue.MemberType; } var toStringMethod = GetObjectToStringMethod(memberType); if (toStringMethod is null) { return false; } var parseMethod = GetObjectParseMethod(memberType); if (parseMethod is null) { return false; } return true; })); }
/// <summary> /// Populates the model with the specified members. /// </summary> /// <param name="context">The serialization context.</param> /// <param name="members">The members.</param> /// <exception cref="ArgumentNullException">The <paramref name="context"/> is <c>null</c>.</exception> /// <exception cref="ArgumentNullException">The <paramref name="members"/> is <c>null</c>.</exception> protected virtual void PopulateModel(ISerializationContext <TSerializationContextInfo> context, List <MemberValue> members) { Argument.IsNotNull("model", context); Argument.IsNotNull("members", members); if (members.Count > 0) { var firstMember = members[0]; if (firstMember.MemberGroup == SerializationMemberGroup.SimpleRootObject) { // Completely replace root object (this is a basic (non-reference) type) context.Model = firstMember.Value; } else if (firstMember.MemberGroup == SerializationMemberGroup.Dictionary) { var targetDictionary = context.Model as IDictionary; if (targetDictionary is null) { throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a dictionary, but target model cannot be updated because it does not implement IDictionary", context.ModelTypeName); } targetDictionary.Clear(); var sourceDictionary = firstMember.Value as IDictionary; if (sourceDictionary != null) { foreach (var key in sourceDictionary.Keys) { targetDictionary.Add(key, sourceDictionary[key]); } } } else if (firstMember.MemberGroup == SerializationMemberGroup.Collection) { if (context.ModelType.IsArrayEx()) { context.Model = firstMember.Value; } else { var targetCollection = context.Model as IList; if (targetCollection is null) { throw Log.ErrorAndCreateException <NotSupportedException>("'{0}' seems to be a collection, but target model cannot be updated because it does not implement IList", context.ModelTypeName); } targetCollection.Clear(); var sourceCollection = firstMember.Value as IEnumerable; if (sourceCollection != null) { foreach (var item in sourceCollection) { targetCollection.Add(item); } } } } else { // Populate using properties var model = context.Model; var modelType = context.ModelType; var modelInfo = _serializationModelCache.GetFromCacheOrFetch(modelType, () => { var catelProperties = SerializationManager.GetCatelProperties(modelType); var fields = SerializationManager.GetFields(modelType); var regularProperties = SerializationManager.GetRegularProperties(modelType); return(new SerializationModelInfo(modelType, catelProperties, fields, regularProperties)); }); foreach (var member in members) { ObjectAdapter.SetMemberValue(model, member, modelInfo); } } } }
public void ThrowsArgumentNullExceptionForNullType() { var serializationManager = new SerializationManager(); ExceptionTester.CallMethodAndExpectException<ArgumentNullException>(() => serializationManager.RemoveSerializerModifier(null, typeof(DynamicSerializerModifier))); ExceptionTester.CallMethodAndExpectException<ArgumentNullException>(() => serializationManager.RemoveSerializerModifier(typeof(DynamicSerializerModifierModel), null)); }
public void ThrowsArgumentNullExceptionForNullType() { var serializationManager = new SerializationManager(); ExceptionTester.CallMethodAndExpectException<ArgumentNullException>(() => serializationManager.GetFieldsToSerialize(null)); }
public void RemovesSerializerModifier() { var serializationManager = new SerializationManager(); serializationManager.AddSerializerModifier<DynamicSerializerModifierModel, DynamicSerializerModifier>(); var modifiers = serializationManager.GetSerializerModifiers(typeof(DynamicSerializerModifierModel)); Assert.AreEqual(1, modifiers.Length); Assert.AreEqual(typeof(DynamicSerializerModifier), modifiers[0].GetType()); serializationManager.RemoveSerializerModifier<DynamicSerializerModifierModel, DynamicSerializerModifier>(); modifiers = serializationManager.GetSerializerModifiers(typeof(DynamicSerializerModifierModel)); Assert.AreEqual(0, modifiers.Length); }
public void ThrowsArgumentNullExceptionForNullType() { var serializationManager = new SerializationManager(); ExceptionTester.CallMethodAndExpectException<ArgumentNullException>(() => serializationManager.GetCatelPropertyNames(null)); }
private static void TestSerializationOnAllSerializers(Action<ISerializer, ISerializationConfiguration, string> action, bool testWithoutGraphIdsAsWell = true, ISerializationManager serializationManager = null) { if (serializationManager == null) { serializationManager = new SerializationManager(); } var serializerConfigurations = new Dictionary<Type, List<ISerializationConfiguration>>(); serializerConfigurations[typeof(XmlSerializer)] = new List<ISerializationConfiguration>(new[] { new SerializationConfiguration() }); serializerConfigurations[typeof(BinarySerializer)] = new List<ISerializationConfiguration>(new[] { new SerializationConfiguration() }); serializerConfigurations[typeof(JsonSerializer)] = new List<ISerializationConfiguration>(new[] { new JsonSerializationConfiguration { UseBson = false }, new JsonSerializationConfiguration { UseBson = true }, }); var serializers = new List<ISerializer>(); serializers.Add(SerializationTestHelper.GetXmlSerializer(XmlSerializerOptimalizationMode.Performance, serializationManager)); serializers.Add(SerializationTestHelper.GetXmlSerializer(XmlSerializerOptimalizationMode.PrettyXml, serializationManager)); serializers.Add(SerializationTestHelper.GetBinarySerializer(serializationManager)); serializers.Add(SerializationTestHelper.GetJsonSerializer(serializationManager)); if (testWithoutGraphIdsAsWell) { var basicJsonSerializer = SerializationTestHelper.GetJsonSerializer(serializationManager); basicJsonSerializer.PreserveReferences = false; basicJsonSerializer.WriteTypeInfo = false; serializers.Add(basicJsonSerializer); } foreach (var serializer in serializers) { var type = serializer.GetType(); var typeName = type.GetSafeFullName(false); var configurations = serializerConfigurations[type]; foreach (var configuration in configurations) { Log.Info(); Log.Info(); Log.Info(); Log.Info("=== TESTING SERIALIZER: {0} ===", typeName); Log.Info(); Log.Info(); Log.Info(); action(serializer, configuration, typeName); } } }