public void NullDeserialization() { EntityMapping.AddMappingProcessor(new TypeDiscoveryProcessor()); EntityMapping.RegisterType(typeof(KnownBaseModel)); var serializer = TypeDiscoverySerializationProvider.Instance.GetSerializer(typeof(KnownBaseModel)); var document = new BsonDocument { { "Item", BsonNull.Value } }; KnownBaseModel deserializedResult; using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); deserializedResult = (KnownBaseModel)serializer.Deserialize(context); } Assert.IsNull(deserializedResult); }
public void NullDeserialization() { var entityMapper = new EntityMapper <KnownBaseModel>(); var serializer = TypeDiscoverySerializationProvider.Instance.GetSerializer(typeof(KnownBaseModel)); var document = new BsonDocument { { "Item", BsonNull.Value } }; KnownBaseModel deserializedResult; using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); deserializedResult = (KnownBaseModel)serializer.Deserialize(context); } Assert.AreEqual(null, deserializedResult); }
public void ReserializingStringIdEntityMaintainsStateExceptNulls() { var foreignProperty = EntityMapping.GetOrCreateDefinition(typeof(StringIdModel)).GetIdProperty(); var serializer = new EntityNavigationCollectionSerializer <StringIdModel>(foreignProperty); var initialCollection = new EntityNavigationCollection <StringIdModel>(foreignProperty) { new StringIdModel { Description = "1" }, new StringIdModel { Id = "5ac383379a5f1303784400f8", Description = "2" } }; EntityNavigationCollection <StringIdModel> deserializedCollection = null; initialCollection.AddForeignId("5ac383379a5f1303784400f9"); var document = new BsonDocument(); using (var writer = new BsonDocumentWriter(document)) { writer.WriteStartDocument(); writer.WriteName("Items"); var context = BsonSerializationContext.CreateRoot(writer); serializer.Serialize(context, initialCollection); writer.WriteEndDocument(); } using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); deserializedCollection = serializer.Deserialize(context) as EntityNavigationCollection <StringIdModel>; } Assert.AreEqual(3, initialCollection.GetForeignIds().Count()); Assert.AreEqual(2, deserializedCollection.GetForeignIds().Count()); Assert.IsTrue(deserializedCollection.GetForeignIds().All(id => initialCollection.GetForeignIds().Contains(id))); }
public void ReserializingObjectIdIdEntityMaintainsState() { var foreignProperty = EntityMapping.GetOrCreateDefinition(typeof(ObjectIdIdModel)).GetIdProperty(); var serializer = new EntityNavigationCollectionSerializer <ObjectIdIdModel>(foreignProperty); var initialCollection = new EntityNavigationCollection <ObjectIdIdModel>(foreignProperty) { new ObjectIdIdModel { Id = ObjectId.GenerateNewId(), Description = "1" } }; EntityNavigationCollection <ObjectIdIdModel> deserializedCollection = null; initialCollection.AddForeignId(ObjectId.GenerateNewId()); var document = new BsonDocument(); using (var writer = new BsonDocumentWriter(document)) { writer.WriteStartDocument(); writer.WriteName("Items"); var context = BsonSerializationContext.CreateRoot(writer); serializer.Serialize(context, initialCollection); writer.WriteEndDocument(); } using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); deserializedCollection = serializer.Deserialize(context) as EntityNavigationCollection <ObjectIdIdModel>; } Assert.AreEqual(2, initialCollection.GetForeignIds().Count()); Assert.AreEqual(2, deserializedCollection.GetForeignIds().Count()); Assert.IsTrue(initialCollection.GetForeignIds().All(id => deserializedCollection.GetForeignIds().Contains(id))); }
public void SerializeICollectionCompatibleButIsntEntityNavigationCollection() { var serializer = new EntityNavigationCollectionSerializer <ObjectIdIdModel>("Id"); var initialCollection = new List <ObjectIdIdModel> { new ObjectIdIdModel { Id = ObjectId.GenerateNewId(), Description = "1" } }; EntityNavigationCollection <ObjectIdIdModel> deserializedCollection = null; var document = new BsonDocument(); using (var writer = new BsonDocumentWriter(document)) { writer.WriteStartDocument(); writer.WriteName("Items"); var context = BsonSerializationContext.CreateRoot(writer); serializer.Serialize(context, initialCollection); writer.WriteEndDocument(); } using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); deserializedCollection = serializer.Deserialize(context) as EntityNavigationCollection <ObjectIdIdModel>; } Assert.AreEqual(1, initialCollection.Count()); Assert.AreEqual(1, deserializedCollection.GetForeignIds().Count()); Assert.IsTrue(initialCollection.Select(e => e.Id).All(id => deserializedCollection.GetForeignIds().Contains(id))); }
public void DeserializingInvalidTypeThrowsException() { var serializer = new EntityNavigationCollectionSerializer <StringIdModel>("Id"); var document = new BsonDocument(new Dictionary <string, object> { { "Items", false } }); using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); serializer.Deserialize(context); } }
public void DeserializingInvalidTypeThrowsException() { var foreignProperty = EntityMapping.GetOrCreateDefinition(typeof(StringIdModel)).GetIdProperty(); var serializer = new EntityNavigationCollectionSerializer <StringIdModel>(foreignProperty); var document = new BsonDocument(new Dictionary <string, object> { { "Items", false } }); using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); serializer.Deserialize(context); } }
public void DeserializingNullReturnsCollection() { var serializer = new EntityNavigationCollectionSerializer <StringIdModel>("Id"); var document = new BsonDocument(new Dictionary <string, object> { { "Items", null } }); using (var reader = new BsonDocumentReader(document)) { reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); var result = serializer.Deserialize(context); Assert.IsNotNull(result); Assert.IsInstanceOfType(result, typeof(EntityNavigationCollection <StringIdModel>)); } }
public static UpdateDefinition <TEntity> Set <TEntity>(this UpdateDefinition <TEntity> definition, string fieldName, BsonValue value) { var dotNetValue = BsonTypeMapper.MapToDotNetValue(value); var valueType = dotNetValue?.GetType(); var reflectedProperty = typeof(TEntity).GetNestedProperty(fieldName); var reflectedValueType = reflectedProperty?.PropertyType; if (valueType == null && reflectedValueType == null) { //For null values - they don't have any type data associated valueType = typeof(object); } else if (valueType == null || (reflectedValueType != null && valueType != reflectedValueType)) { //Where BsonTypeMapper can't determine the type or it is a mismatch to what is reflected from the type //The preference is on the reflected type and the serializer on the specific member valueType = reflectedValueType; //We will need the serializer defined for the specific member //Not all serializers will be registered (eg. EntityNavigationSerializer) so we need to look it up manually var declaringClassMap = BsonClassMap.LookupClassMap(reflectedProperty.DeclaringType); var memberMap = declaringClassMap.GetMemberMap(reflectedProperty.Name); var serializer = memberMap.GetSerializer(); //To prevent re-serializing back to a string, we use the BsonDocumentReader over JsonReader //Using BsonDocumentReader means the root must be a BsonDocument. Because the value may be a BsonArray, we need to wrap the value. var containerDocument = new BsonDocument { { "Value", value } }; using (var reader = new BsonDocumentReader(containerDocument)) { //Get the reader into a state where the serializer is starting on the right element reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); dotNetValue = serializer.Deserialize(context); } } var typeArgs = new[] { typeof(TEntity), valueType }; var specificDefinitionType = typeof(StringFieldDefinition <,>).MakeGenericType(typeArgs); var specificDefinition = Activator.CreateInstance(specificDefinitionType, fieldName, null); //ie. StringFieldDefintion<TEntity, valueType> var expressionType = typeof(Expression); var setMethod = typeof(MongoDB.Driver.UpdateDefinitionExtensions) .GetMethods() .Where(m => m.Name == "Set" && !m.GetParameters().Any(p => expressionType.IsAssignableFrom(p.ParameterType))) .FirstOrDefault() .MakeGenericMethod(typeArgs); //Breaking down the above reflection, we are trying to get the "Set" method that doesn't take an "Expression" as a parameter //The method we want takes an `UpdateDefinition`, `FieldDefinition` and `Value` as the 3 parameters //Accounting for the variables and types, the method call would look something, something like the following //MongoDB.Driver.UpdateDefinitionExtensions.Set<TEntity, TField>(UpdateDefinition<TEntity> definition, StringFieldDefinition<TEntity, TField> specificDefinition, dotNetValue) var result = setMethod.Invoke(null, new[] { definition, specificDefinition, dotNetValue }); return(result as UpdateDefinition <TEntity>); }
public static UpdateDefinition <TEntity> Set <TEntity>(this UpdateDefinition <TEntity> definition, string fieldName, BsonValue value) where TEntity : class { var dotNetValue = BsonTypeMapper.MapToDotNetValue(value); var valueType = dotNetValue?.GetType(); IEntityProperty propertyDefinition = null; if (EntityMapping.IsValidTypeToMap(typeof(TEntity))) { propertyDefinition = EntityMapping.GetOrCreateDefinition(typeof(TEntity)) .TraverseProperties() .Where(p => p.FullPath == fieldName) .FirstOrDefault(); } var propertyType = propertyDefinition?.PropertyType; if (valueType == null && propertyType == null) { //For null values - they don't have any type data associated valueType = typeof(object); } else if (valueType == null || (propertyType != null && valueType != propertyType)) { //Where BsonTypeMapper can't determine the type or it is a mismatch to what is set in the entity definition //The preference is on the definition type and the serializer on the specific member valueType = propertyType; //We will need the serializer defined for the specific member //Not all serializers will be registered (eg. EntityNavigationSerializer) so we need to look it up manually var declaringClassMap = BsonClassMap.LookupClassMap(propertyDefinition.EntityType); var memberMap = declaringClassMap.GetMemberMapForElement(propertyDefinition.ElementName); var serializer = memberMap.GetSerializer(); //To prevent re-serializing back to a string, we use the BsonDocumentReader over JsonReader //Using BsonDocumentReader means the root must be a BsonDocument. Because the value may be a BsonArray, we need to wrap the value. var containerDocument = new BsonDocument { { "Value", value } }; using (var reader = new BsonDocumentReader(containerDocument)) { //Get the reader into a state where the serializer is starting on the right element reader.ReadBsonType(); reader.ReadStartDocument(); reader.ReadBsonType(); reader.SkipName(); var context = BsonDeserializationContext.CreateRoot(reader); dotNetValue = serializer.Deserialize(context); } } var typeArgs = new[] { typeof(TEntity), valueType }; var specificDefinitionType = typeof(StringFieldDefinition <,>).MakeGenericType(typeArgs); var specificDefinition = Activator.CreateInstance(specificDefinitionType, fieldName, null); //ie. StringFieldDefintion<TEntity, valueType> foreach (var method in typeof(UpdateDefinitionExtensions).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)) { if (method.Name == nameof(InternalSet)) { var internalSetMethod = method.MakeGenericMethod(typeArgs); var result = internalSetMethod.Invoke(null, new[] { definition, specificDefinition, dotNetValue }); return(result as UpdateDefinition <TEntity>); } } return(default);