/// <summary> /// Deserializes an object from a BsonReader. /// </summary> /// <param name="bsonReader">The BsonReader.</param> /// <param name="nominalType">The nominal type of the object.</param> /// <param name="options">The serialization options.</param> /// <returns>An object.</returns> public override object Deserialize( BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options ) { if (nominalType != typeof(object)) { var message = string.Format("ObjectSerializer called for nominal type {0}.", nominalType.FullName); throw new InvalidOperationException(message); } var bsonType = bsonReader.CurrentBsonType; if (bsonType == BsonType.Null) { bsonReader.ReadNull(); return null; } else if (bsonType == BsonType.Document) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); if (bsonReader.ReadBsonType() == BsonType.EndOfDocument) { bsonReader.ReadEndDocument(); return new object(); } else { bsonReader.ReturnToBookmark(bookmark); } } var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(object)); var actualType = discriminatorConvention.GetActualType(bsonReader, typeof(object)); if (actualType == typeof(object)) { var message = string.Format("Unable to determine actual type of object to deserialize. NominalType is System.Object and BsonType is {0}.", bsonType); throw new FileFormatException(message); } var serializer = BsonSerializer.LookupSerializer(actualType); return serializer.Deserialize(bsonReader, nominalType, actualType, null); }
public void TestBookmark() { var json = "{ \"x\" : 1, \"y\" : 2 }"; using (bsonReader = BsonReader.Create(json)) { // do everything twice returning to bookmark in between var bookmark = bsonReader.GetBookmark(); Assert.AreEqual(BsonType.Document, bsonReader.ReadBsonType()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual(BsonType.Document, bsonReader.ReadBsonType()); bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); bsonReader.ReturnToBookmark(bookmark); bsonReader.ReadStartDocument(); bookmark = bsonReader.GetBookmark(); Assert.AreEqual(BsonType.Int32, bsonReader.ReadBsonType()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual(BsonType.Int32, bsonReader.ReadBsonType()); bookmark = bsonReader.GetBookmark(); Assert.AreEqual("x", bsonReader.ReadName()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual("x", bsonReader.ReadName()); bookmark = bsonReader.GetBookmark(); Assert.AreEqual(1, bsonReader.ReadInt32()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual(1, bsonReader.ReadInt32()); bookmark = bsonReader.GetBookmark(); Assert.AreEqual(BsonType.Int32, bsonReader.ReadBsonType()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual(BsonType.Int32, bsonReader.ReadBsonType()); bookmark = bsonReader.GetBookmark(); Assert.AreEqual("y", bsonReader.ReadName()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual("y", bsonReader.ReadName()); bookmark = bsonReader.GetBookmark(); Assert.AreEqual(2, bsonReader.ReadInt32()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual(2, bsonReader.ReadInt32()); bookmark = bsonReader.GetBookmark(); Assert.AreEqual(BsonType.EndOfDocument, bsonReader.ReadBsonType()); bsonReader.ReturnToBookmark(bookmark); Assert.AreEqual(BsonType.EndOfDocument, bsonReader.ReadBsonType()); bookmark = bsonReader.GetBookmark(); bsonReader.ReadEndDocument(); bsonReader.ReturnToBookmark(bookmark); bsonReader.ReadEndDocument(); Assert.AreEqual(BsonReaderState.Done, bsonReader.State); } Assert.AreEqual(json, BsonSerializer.Deserialize<BsonDocument>(new StringReader(json)).ToJson()); }
public Type GetActualType(BsonReader bsonReader, Type nominalType) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; if (bsonReader.FindElement("Type")) { var discriminator = BsonValue.ReadFrom(bsonReader); actualType = BsonSerializer.LookupActualType(nominalType, discriminator); } bsonReader.ReturnToBookmark(bookmark); return actualType; }
public Type GetActualType( BsonReader bsonReader, Type nominalType ) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; while(bsonReader.ReadBsonType() != BsonType.EndOfDocument) { var name = bsonReader.ReadName(); if(name == "OnlyInB") { actualType = typeof(B); break; } else if(name == "OnlyInC") { actualType = typeof(C); break; } bsonReader.SkipValue(); } bsonReader.ReturnToBookmark(bookmark); return actualType; }
// private methods private Type GetActualType(BsonReader bsonReader) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); if (bsonReader.FindElement("type")) { var type = bsonReader.ReadString(); bsonReader.ReturnToBookmark(bookmark); switch (type) { case "link": return typeof(GeoJsonLinkedCoordinateReferenceSystem); case "name": return typeof(GeoJsonNamedCoordinateReferenceSystem); default: var message = string.Format("The type field of the GeoJsonCoordinateReferenceSystem is not valid: '{0}'.", type); throw new FormatException(message); } } else { throw new FormatException("GeoJsonCoordinateReferenceSystem object is missing the type field."); } }
public override object Deserialize( BsonReader bsonReader, Type nominalType ) { if (nominalType != typeof(object)) { var message = string.Format("ObjectSerializer called for type: {0}", nominalType.FullName); throw new InvalidOperationException(message); } var bsonType = bsonReader.CurrentBsonType; if (bsonType == BsonType.Null) { bsonReader.ReadNull(); return null; } else if (bsonType == BsonType.Document) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); switch (bsonReader.ReadBsonType()) { case BsonType.EndOfDocument: bsonReader.ReadEndDocument(); return new object(); default: bsonReader.ReturnToBookmark(bookmark); var discriminatorConvention = BsonDefaultSerializer.LookupDiscriminatorConvention(typeof(object)); var actualType = discriminatorConvention.GetActualType(bsonReader, typeof(object)); if (actualType == typeof(object)) { throw new BsonSerializationException("Unable to determine actual type of document to deserialize"); } var serializer = BsonSerializer.LookupSerializer(actualType); return serializer.Deserialize(bsonReader, nominalType, actualType); } } else { var message = string.Format("Cannot deserialize an object from BsonType: {0}", bsonType); throw new FileFormatException(message); } }
// public methods /// <summary> /// Gets the actual type of an object by reading the discriminator from a BsonReader. /// </summary> /// <param name="bsonReader">The reader.</param> /// <param name="nominalType">The nominal type.</param> /// <returns>The actual type.</returns> public Type GetActualType(BsonReader bsonReader, Type nominalType) { // the BsonReader is sitting at the value whose actual type needs to be found var bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.Document) { // ensure KnownTypes of nominalType are registered (so IsTypeDiscriminated returns correct answer) BsonSerializer.EnsureKnownTypesAreRegistered(nominalType); // we can skip looking for a discriminator if nominalType has no discriminated sub types if (BsonSerializer.IsTypeDiscriminated(nominalType)) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; if (bsonReader.FindElement(_elementName)) { var context = BsonDeserializationContext.CreateRoot<BsonValue>(bsonReader); var discriminator = BsonValueSerializer.Instance.Deserialize(context); if (discriminator.IsBsonArray) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } actualType = BsonSerializer.LookupActualType(nominalType, discriminator); } bsonReader.ReturnToBookmark(bookmark); return actualType; } } return nominalType; }
// public methods /// <summary> /// Gets the actual type of an object by reading the discriminator from a BsonReader. /// </summary> /// <param name="bsonReader">The reader.</param> /// <param name="nominalType">The nominal type.</param> /// <returns>The actual type.</returns> public Type GetActualType(BsonReader bsonReader, Type nominalType) { // the BsonReader is sitting at the value whose actual type needs to be found var bsonType = bsonReader.CurrentBsonType; if (bsonReader.State == BsonReaderState.Value) { Type primitiveType = null; switch (bsonType) { case BsonType.Boolean: primitiveType = typeof(bool); break; case BsonType.Binary: var bookmark = bsonReader.GetBookmark(); byte[] bytes; BsonBinarySubType subType; bsonReader.ReadBinaryData(out bytes, out subType); if (subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy) { primitiveType = typeof(Guid); } bsonReader.ReturnToBookmark(bookmark); break; case BsonType.DateTime: primitiveType = typeof(DateTime); break; case BsonType.Double: primitiveType = typeof(double); break; case BsonType.Int32: primitiveType = typeof(int); break; case BsonType.Int64: primitiveType = typeof(long); break; case BsonType.ObjectId: primitiveType = typeof(ObjectId); break; case BsonType.String: primitiveType = typeof(string); break; } if (primitiveType != null && nominalType.IsAssignableFrom(primitiveType)) { return primitiveType; } } if (bsonType == BsonType.Document) { // ensure KnownTypes of nominalType are registered (so IsTypeDiscriminated returns correct answer) BsonDefaultSerializer.EnsureKnownTypesAreRegistered(nominalType); // we can skip looking for a discriminator if nominalType has no discriminated sub types if (BsonDefaultSerializer.IsTypeDiscriminated(nominalType)) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; if (bsonReader.FindElement(_elementName)) { var discriminator = BsonValue.ReadFrom(bsonReader); if (discriminator.IsBsonArray) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } actualType = BsonDefaultSerializer.LookupActualType(nominalType, discriminator); } bsonReader.ReturnToBookmark(bookmark); return actualType; } } return nominalType; }
private bool IsCSharpNullRepresentation(BsonReader bsonReader) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var bsonType = bsonReader.ReadBsonType(); if (bsonType == BsonType.Boolean) { var name = bsonReader.ReadName(); if (name == "_csharpnull" || name == "$csharpnull") { var value = bsonReader.ReadBoolean(); if (value) { bsonType = bsonReader.ReadBsonType(); if (bsonType == BsonType.EndOfDocument) { bsonReader.ReadEndDocument(); return true; } } } } bsonReader.ReturnToBookmark(bookmark); return false; }
// public methods /// <summary> /// Gets the actual type of an object by reading the discriminator from a BsonReader. /// </summary> /// <param name="bsonReader">The reader.</param> /// <param name="nominalType">The nominal type.</param> /// <returns>The actual type.</returns> public Type GetActualType(BsonReader bsonReader, Type nominalType) { // the BsonReader is sitting at the value whose actual type needs to be found var bsonType = bsonReader.GetCurrentBsonType(); if (bsonReader.State == BsonReaderState.Value) { Type primitiveType = null; switch (bsonType) { case BsonType.Boolean: primitiveType = typeof(bool); break; case BsonType.Binary: var bookmark = bsonReader.GetBookmark(); var binaryData = bsonReader.ReadBinaryData(); var subType = binaryData.SubType; if (subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy) { primitiveType = typeof(Guid); } bsonReader.ReturnToBookmark(bookmark); break; case BsonType.DateTime: primitiveType = typeof(DateTime); break; case BsonType.Double: primitiveType = typeof(double); break; case BsonType.Int32: primitiveType = typeof(int); break; case BsonType.Int64: primitiveType = typeof(long); break; case BsonType.ObjectId: primitiveType = typeof(ObjectId); break; case BsonType.String: primitiveType = typeof(string); break; } // Type.IsAssignableFrom is extremely expensive, always perform a direct type check before calling Type.IsAssignableFrom if (primitiveType != null && (primitiveType == nominalType || nominalType.IsAssignableFrom(primitiveType))) { return primitiveType; } } if (bsonType == BsonType.Document) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; if (bsonReader.FindElement(_elementName)) { var context = BsonDeserializationContext.CreateRoot<BsonValue>(bsonReader); var discriminator = BsonValueSerializer.Instance.Deserialize(context); if (discriminator.IsBsonArray) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } actualType = BsonSerializer.LookupActualType(nominalType, discriminator); } bsonReader.ReturnToBookmark(bookmark); return actualType; } return nominalType; }
// BsonReader is sitting at the value whose actual type needs to be found public Type GetActualType( BsonReader bsonReader, Type nominalType ) { var bsonType = bsonReader.CurrentBsonType; if (bsonReader.State == BsonReaderState.Value) { Type primitiveType = null; switch (bsonType) { case BsonType.Boolean: primitiveType = typeof(bool); break; case BsonType.Binary: var bookmark = bsonReader.GetBookmark(); byte[] bytes; BsonBinarySubType subType; bsonReader.ReadBinaryData(out bytes, out subType); if (subType == BsonBinarySubType.Uuid && bytes.Length == 16) { primitiveType = typeof(Guid); } bsonReader.ReturnToBookmark(bookmark); break; case BsonType.DateTime: primitiveType = typeof(DateTime); break; case BsonType.Double: primitiveType = typeof(double); break; case BsonType.Int32: primitiveType = typeof(int); break; case BsonType.Int64: primitiveType = typeof(long); break; case BsonType.ObjectId: primitiveType = typeof(ObjectId); break; case BsonType.String: primitiveType = typeof(string); break; } if (primitiveType != null && nominalType.IsAssignableFrom(primitiveType)) { return primitiveType; } } if (bsonType == BsonType.Document) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; if (bsonReader.FindElement(elementName)) { var discriminator = BsonValue.ReadFrom(bsonReader); if (discriminator.IsBsonArray) { discriminator = discriminator.AsBsonArray.Last(); // last item is leaf class discriminator } actualType = BsonDefaultSerializer.LookupActualType(nominalType, discriminator); } bsonReader.ReturnToBookmark(bookmark); return actualType; } return nominalType; }
public override object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options) { var bsonType = bsonReader.CurrentBsonType; if (bsonType == BsonType.Null) { bsonReader.ReadNull(); return null; } else if (bsonType == BsonType.Document) { var os = new ObjectSerializer(); MongoDynamic md = new MongoDynamic(); bsonReader.ReadStartDocument(); Dictionary<string, Type> typeMap = null; // scan document first to find interfaces { var bookMark = bsonReader.GetBookmark(); if (bsonReader.FindElement(MongoDynamic.InterfacesField)) { md[MongoDynamic.InterfacesField] = BsonSerializer.Deserialize<BsonValue>(bsonReader).AsBsonArray.Select(x => x.AsString); typeMap = md.GetTypeMap(); } else { throw new FormatException("No interfaces defined for this dynamic object - can't deserialize it"); } bsonReader.ReturnToBookmark(bookMark); } while (bsonReader.ReadBsonType() != BsonType.EndOfDocument) { var name = bsonReader.ReadName(); if (name == "_id") { //md[name] = BsonValue.ReadFrom(bsonReader).AsObjectId; md[name] = BsonSerializer.Deserialize<ObjectId>(bsonReader); } else if (name == MongoDynamic.InterfacesField) { // Read it and ignore it, we already have it //BsonValue.ReadFrom(bsonReader); BsonSerializer.Deserialize<ObjectId>(bsonReader); } else { if (typeMap == null) throw new FormatException("No interfaces define for this dynamic object - can't deserialize"); // lookup the type for this element according to the interfaces Type elementType; if (typeMap.TryGetValue(name, out elementType)) { var value = BsonSerializer.Deserialize(bsonReader, elementType); md[name] = value; } else { // This is a value that is no longer in the interface, maybe a column you removed // not really much we can do with it ... but we need to read it and move on var value = BsonSerializer.Deserialize(bsonReader, typeof(object)); md[name] = value; // As with all databases, removing elements from the schema is always going to cause problems ... } } } bsonReader.ReadEndDocument(); return md; } else { var message = string.Format("Can't deserialize a {0} from BsonType {1}.", nominalType.FullName, bsonType); throw new FormatException(message); } }