public Type GetActualType(IBsonReader bsonReader, Type nominalType) { if (nominalType == typeof(JobTask)) { var ret = nominalType; var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); if (bsonReader.FindElement(ElementName)) { var value = bsonReader.ReadString(); ret = Type.GetType(value); if (ret == null) throw new Exception("Could not find type " + value); if (!ret.IsSubclassOf(typeof(JobTask))) throw new Exception("Database type does not inherit from JobTask."); } bsonReader.ReturnToBookmark(bookmark); return ret; } else { return nominalType; } }
public Type GetActualType(IBsonReader bsonReader, Type nominalType) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); string typeValue = string.Empty; if (bsonReader.FindElement(ElementName)) typeValue = bsonReader.ReadString(); else throw new NotSupportedException(); bsonReader.ReturnToBookmark(bookmark); var retr = Type.GetType(typeValue) ?? Type.GetType("ThreeOneThree.Proxima.Core.Entities." + typeValue); return retr; }
public Type GetActualType(IBsonReader 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; }
// 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(IBsonReader 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(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 void TestBookmark() { var json = "{ \"x\" : 1, \"y\" : 2 }"; using (_bsonReader = new JsonReader(json)) { // do everything twice returning to bookmark in between var bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.Document, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.Document, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); _bsonReader.ReadStartDocument(); _bsonReader.ReturnToBookmark(bookmark); _bsonReader.ReadStartDocument(); bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); Assert.Equal("x", _bsonReader.ReadName()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal("x", _bsonReader.ReadName()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(1, _bsonReader.ReadInt32()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(1, _bsonReader.ReadInt32()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); Assert.Equal("y", _bsonReader.ReadName()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal("y", _bsonReader.ReadName()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(2, _bsonReader.ReadInt32()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(2, _bsonReader.ReadInt32()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.EndOfDocument, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.EndOfDocument, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); _bsonReader.ReadEndDocument(); _bsonReader.ReturnToBookmark(bookmark); _bsonReader.ReadEndDocument(); Assert.Equal(BsonReaderState.Initial, _bsonReader.State); } Assert.Equal(json, BsonSerializer.Deserialize<BsonDocument>(json).ToJson()); }
// 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(IBsonReader 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.Decimal128: primitiveType = typeof(Decimal128); 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.GetTypeInfo().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(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; }
/// <summary> /// Deserializes an object from a binary source. /// </summary> /// <param name="Reader">Binary deserializer.</param> /// <param name="DataType">Optional datatype. If not provided, will be read from the binary source.</param> /// <param name="Embedded">If the object is embedded into another.</param> /// <param name="CheckFieldNames">If field names are to be extended.</param> /// <returns>Deserialized object.</returns> public object Deserialize(IBsonReader Reader, BsonType?DataType, bool Embedded, bool CheckFieldNames) { BsonReaderBookmark Bookmark = Reader.GetBookmark(); BsonType? DataTypeBak = DataType; if (!DataType.HasValue) { DataType = Reader.ReadBsonType(); } switch (DataType.Value) { case BsonType.Document: break; case BsonType.Boolean: return(Reader.ReadBoolean()); case BsonType.Int32: return(Reader.ReadInt32()); case BsonType.Int64: return(Reader.ReadInt64()); case BsonType.Decimal128: return((decimal)Reader.ReadDecimal128()); case BsonType.Double: return(Reader.ReadDouble()); case BsonType.DateTime: return(ObjectSerializer.UnixEpoch.AddMilliseconds(Reader.ReadDateTime())); case BsonType.String: case BsonType.Symbol: case BsonType.JavaScript: case BsonType.JavaScriptWithScope: return(Reader.ReadString()); case BsonType.Binary: return(Reader.ReadBytes()); case BsonType.Null: Reader.ReadNull(); return(null); default: throw new Exception("Object or value expected."); } LinkedList <KeyValuePair <string, object> > Properties = new LinkedList <KeyValuePair <string, object> >(); LinkedList <KeyValuePair <string, object> > LowerCase = null; string TypeName = string.Empty; Guid ObjectId = Guid.Empty; string CollectionName = string.Empty; string FieldName; BsonType ValueType; object Value; Reader.ReadStartDocument(); while (Reader.State == BsonReaderState.Type) { ValueType = Reader.ReadBsonType(); if (ValueType == BsonType.EndOfDocument) { break; } FieldName = Reader.ReadName(); switch (ValueType) { case BsonType.Array: Value = GeneratedObjectSerializerBase.ReadArray(null, this.Provider, Reader, ValueType); break; case BsonType.Binary: Value = Reader.ReadBytes(); break; case BsonType.Boolean: Value = Reader.ReadBoolean(); break; case BsonType.DateTime: Value = ObjectSerializer.UnixEpoch.AddMilliseconds(Reader.ReadDateTime()); break; case BsonType.Decimal128: Value = (decimal)Reader.ReadDecimal128(); break; case BsonType.Document: Value = this.Deserialize(Reader, ValueType, true); break; case BsonType.Double: Value = Reader.ReadDouble(); break; case BsonType.Int32: Value = Reader.ReadInt32(); break; case BsonType.Int64: Value = Reader.ReadInt64(); break; case BsonType.JavaScript: Value = Reader.ReadJavaScript(); break; case BsonType.JavaScriptWithScope: Value = Reader.ReadJavaScriptWithScope(); break; case BsonType.Null: Value = null; Reader.ReadNull(); break; case BsonType.ObjectId: Value = Reader.ReadObjectId(); break; case BsonType.String: Value = Reader.ReadString(); break; case BsonType.Symbol: Value = Reader.ReadSymbol(); break; default: throw new Exception("Unrecognized data type: " + ValueType.ToString()); } switch (FieldName) { case "_id": if (Value is Guid Guid) { ObjectId = Guid; } else if (Value is string s) { ObjectId = new Guid(s); } else if (Value is byte[] A) { ObjectId = new Guid(A); } else if (Value is ObjectId ObjId) { ObjectId = GeneratedObjectSerializerBase.ObjectIdToGuid(ObjId); } else { throw new Exception("Unrecognized Object ID type: " + Value.GetType().FullName); } break; case "_type": TypeName = Value?.ToString(); if (this.returnTypedObjects && !string.IsNullOrEmpty(TypeName)) { Type DesiredType = Types.GetType(TypeName); if (DesiredType is null) { DesiredType = typeof(GenericObject); } if (DesiredType != typeof(GenericObject)) { IObjectSerializer Serializer2 = this.provider.GetObjectSerializer(DesiredType); Reader.ReturnToBookmark(Bookmark); return(Serializer2.Deserialize(Reader, DataTypeBak, Embedded)); } } break; case "_collection": CollectionName = Value?.ToString(); break; default: if (FieldName.EndsWith("_L")) { string s = FieldName.Substring(0, FieldName.Length - 2); bool Ignore = false; foreach (KeyValuePair <string, object> P in Properties) { if (P.Key == s) { Ignore = true; break; } } if (!Ignore) { if (LowerCase is null) { LowerCase = new LinkedList <KeyValuePair <string, object> >(); } LowerCase.AddLast(new KeyValuePair <string, object>(s, Value)); } } else { Properties.AddLast(new KeyValuePair <string, object>(FieldName, Value)); } break; } } if (!(LowerCase is null)) { foreach (KeyValuePair <string, object> P in LowerCase) { bool Ignore = false; foreach (KeyValuePair <string, object> P2 in Properties) { if (P2.Key == P.Key) { Ignore = true; break; } } if (!Ignore) { Properties.AddLast(new KeyValuePair <string, object>(P.Key + "_L", P.Value)); } } } Reader.ReadEndDocument(); return(new GenericObject(CollectionName, TypeName, ObjectId, Properties)); }
public void TestBookmark() { var json = "{ \"x\" : 1, \"y\" : 2 }"; using (_bsonReader = new JsonReader(json)) { // do everything twice returning to bookmark in between var bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.Document, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.Document, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); _bsonReader.ReadStartDocument(); _bsonReader.ReturnToBookmark(bookmark); _bsonReader.ReadStartDocument(); bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); Assert.Equal("x", _bsonReader.ReadName()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal("x", _bsonReader.ReadName()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(1, _bsonReader.ReadInt32()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(1, _bsonReader.ReadInt32()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.Int32, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); Assert.Equal("y", _bsonReader.ReadName()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal("y", _bsonReader.ReadName()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(2, _bsonReader.ReadInt32()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(2, _bsonReader.ReadInt32()); bookmark = _bsonReader.GetBookmark(); Assert.Equal(BsonType.EndOfDocument, _bsonReader.ReadBsonType()); _bsonReader.ReturnToBookmark(bookmark); Assert.Equal(BsonType.EndOfDocument, _bsonReader.ReadBsonType()); bookmark = _bsonReader.GetBookmark(); _bsonReader.ReadEndDocument(); _bsonReader.ReturnToBookmark(bookmark); _bsonReader.ReadEndDocument(); Assert.Equal(BsonReaderState.Initial, _bsonReader.State); } Assert.Equal(json, BsonSerializer.Deserialize <BsonDocument>(json).ToJson()); }