/// <summary> /// Ensures that the BsonType equals the expected type. /// </summary> /// <param name="reader">The reader.</param> /// <param name="bsonType">The expected type.</param> protected void EnsureBsonTypeEquals(IBsonReader reader, BsonType bsonType) { if (reader.GetCurrentBsonType() != bsonType) { throw CreateCannotDeserializeFromBsonTypeException(reader.GetCurrentBsonType()); } }
public FieldValueChange Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { FieldValueChange fieldValueChange = new FieldValueChange(); IBsonReader reader = context.Reader; BsonType bysonType = reader.GetCurrentBsonType(); if (bysonType == BsonType.Document) { reader.ReadStartDocument(); string name = reader.ReadName(); fieldValueChange.OriginalValue = base.Deserialize(context, args); name = reader.ReadName(); fieldValueChange.NewValue = base.Deserialize(context, args); reader.ReadEndDocument(); return(fieldValueChange); } else { fieldValueChange.OriginalValue = base.Deserialize(context, args); } return(fieldValueChange); }
/***************************************************/ public override object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { IBsonReader reader = context.Reader; BsonType currentBsonType = reader.GetCurrentBsonType(); switch (currentBsonType) { case BsonType.Array: if (context.DynamicArraySerializer != null) { return(context.DynamicArraySerializer.Deserialize(context)); } break; case BsonType.Binary: { BsonBinaryData bsonBinaryData = reader.ReadBinaryData(); BsonBinarySubType subType = bsonBinaryData.SubType; if (subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy) { return(bsonBinaryData.ToGuid()); } break; } case BsonType.Boolean: return(reader.ReadBoolean()); case BsonType.DateTime: return(new BsonDateTime(reader.ReadDateTime()).ToUniversalTime()); case BsonType.Decimal128: return(reader.ReadDecimal128()); case BsonType.Document: return(DeserializeDiscriminatedValue(context, args)); case BsonType.Double: return(reader.ReadDouble()); case BsonType.Int32: return(reader.ReadInt32()); case BsonType.Int64: return(reader.ReadInt64()); case BsonType.Null: reader.ReadNull(); return(null); case BsonType.ObjectId: return(reader.ReadObjectId()); case BsonType.String: return(reader.ReadString()); } Engine.Reflection.Compute.RecordError($"ObjectSerializer does not support BSON type '{currentBsonType}'."); return(null); }
/***************************************************/ /**** Interface Methods ****/ /***************************************************/ 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) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; if (bsonReader.FindElement(ElementName)) { var context = BsonDeserializationContext.CreateRoot(bsonReader); var discriminator = BsonValueSerializer.Instance.Deserialize(context); actualType = BsonSerializer.LookupActualType(nominalType, discriminator); } else { actualType = typeof(CustomObject); } bsonReader.ReturnToBookmark(bookmark); return(actualType); } return(nominalType); }
/***************************************************/ /**** Interface Methods ****/ /***************************************************/ public Type GetActualType(IBsonReader bsonReader, Type nominalType) { Type actualType = nominalType; // the BsonReader is sitting at the value whose actual type needs to be found BsonType bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.Document) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); 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 } if (BsonSerializer.IsTypeDiscriminated(nominalType)) { actualType = BsonSerializer.LookupActualType(nominalType, discriminator); } } 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 <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); }
static object ReadObject(IBsonReader bsonReader) //_120509_173140 keep consistent { switch (bsonReader.GetCurrentBsonType()) { case BsonType.Array: return(ReadArray(bsonReader)); // replacement case BsonType.Binary: var binary = BsonSerializer.Deserialize <BsonValue>(bsonReader); return(BsonTypeMapper.MapToDotNetValue(binary) ?? binary); // byte[] or Guid else self case BsonType.Boolean: return(bsonReader.ReadBoolean()); case BsonType.DateTime: return(BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(bsonReader.ReadDateTime())); case BsonType.Document: return(ReadCustomObject(bsonReader)); // replacement case BsonType.Double: return(bsonReader.ReadDouble()); case BsonType.Int32: return(bsonReader.ReadInt32()); case BsonType.Int64: return(bsonReader.ReadInt64()); case BsonType.Null: bsonReader.ReadNull(); return(null); case BsonType.ObjectId: return(bsonReader.ReadObjectId()); case BsonType.String: return(bsonReader.ReadString()); default: return(BsonSerializer.Deserialize <BsonValue>(bsonReader)); } }
// 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; }
private void DeserializeDataPointAttribute(string attr, IBsonReader reader, ref DataPoint dataPoint) { switch (attr) { case "Value": dataPoint.Value = reader.ReadDecimal128().ToDecimal(); break; case "Unit": if (reader.GetCurrentBsonType() == BsonType.Null) { reader.ReadNull(); dataPoint.Unit = null; } else { dataPoint.Unit = reader.ReadString(); } break; case "Precision": if (reader.GetCurrentBsonType() == BsonType.Null) { reader.ReadNull(); dataPoint.Precision = null; } dataPoint.Precision = reader.ReadDouble(); break; case "Accuracy": if (reader.GetCurrentBsonType() == BsonType.Null) { reader.ReadNull(); dataPoint.Accuracy = null; } dataPoint.Accuracy = reader.ReadDouble(); break; default: throw new DatabaseException("Unknown document attribute", "Measurements"); } }
internal static object Deserialize(IBsonReader reader) { switch (reader.GetCurrentBsonType()) { case BsonType.ObjectId: return(reader.ReadObjectId()); case BsonType.Boolean: return(reader.ReadBoolean()); case BsonType.DateTime: return(UnixTime.ToDateTime(reader.ReadDateTime())); case BsonType.Int32: return(reader.ReadInt32()); case BsonType.Binary: return(reader.ReadBytes()); case BsonType.Int64: return(reader.ReadInt64()); case BsonType.Double: return(reader.ReadDouble()); case BsonType.Null: reader.ReadNull(); return(null); case BsonType.String: return(reader.ReadString()); default: throw new InvalidOperationException( $"Cannot deserialize {reader.GetCurrentBsonType()} to native value."); } }
public override bool Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { IBsonReader bsonReader = context.Reader; BsonType bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.String) { string token = bsonReader.ReadString(); return(ParseBoolean.FromString(token)); } else { return(base.Deserialize(context, args)); } }
public override bool Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { IBsonReader bsonReader = context.Reader; BsonType bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.String) { string value = bsonReader.ReadString().ToLower(); if (value == "") { return(false); } return(JsonConvert.ToBoolean(bsonReader.ReadString().ToLower())); } return(base.Deserialize(context, args)); }
/***************************************************/ /**** Interface Methods ****/ /***************************************************/ 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) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); var actualType = nominalType; if (bsonReader.FindElement(ElementName)) { var context = BsonDeserializationContext.CreateRoot(bsonReader); var discriminator = BsonValueSerializer.Instance.Deserialize(context); try { actualType = BsonSerializer.LookupActualType(nominalType, discriminator); } catch { BsonDocument doc = new BsonDocument { { "_t", "System.Type" }, { "Name", discriminator.ToString() } }; try { actualType = Convert.FromBson(doc) as Type; } catch { } } } else { actualType = typeof(CustomObject); } bsonReader.ReturnToBookmark(bookmark); return(actualType); } return(nominalType); }
static object ReadObject(IBsonReader bsonReader) //_120509_173140 sync, test { switch (bsonReader.GetCurrentBsonType()) { case BsonType.Array: return(ReadArray(bsonReader)); // replacement case BsonType.Boolean: return(bsonReader.ReadBoolean()); case BsonType.DateTime: return(BsonUtils.ToDateTimeFromMillisecondsSinceEpoch(bsonReader.ReadDateTime())); case BsonType.Decimal128: return(Decimal128.ToDecimal(bsonReader.ReadDecimal128())); case BsonType.Document: return(ReadCustomObject(bsonReader)); // replacement case BsonType.Double: return(bsonReader.ReadDouble()); case BsonType.Int32: return(bsonReader.ReadInt32()); case BsonType.Int64: return(bsonReader.ReadInt64()); case BsonType.Null: bsonReader.ReadNull(); return(null); case BsonType.ObjectId: return(bsonReader.ReadObjectId()); case BsonType.String: return(bsonReader.ReadString()); case BsonType.Binary: var data = bsonReader.ReadBinaryData(); switch (data.SubType) { case BsonBinarySubType.UuidLegacy: case BsonBinarySubType.UuidStandard: return(data.ToGuid()); default: return(data); } default: return(BsonSerializer.Deserialize <BsonValue>(bsonReader)); } }
/***************************************************/ /**** Interface Methods ****/ /***************************************************/ public Type GetActualType(IBsonReader bsonReader, Type nominalType) { Type actualType = nominalType; // the BsonReader is sitting at the value whose actual type needs to be found BsonType bsonType = bsonReader.GetCurrentBsonType(); if (bsonType == BsonType.Document) { var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); 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 } if (BsonSerializer.IsTypeDiscriminated(nominalType)) { actualType = BsonSerializer.LookupActualType(nominalType, discriminator); } else if (Reflection.Compute.UnqualifiedName(nominalType.FullName) != Reflection.Compute.UnqualifiedName(discriminator.ToString()) && Config.AllowUpgradeFromBson && !Config.TypesWithoutUpgrade.Contains(actualType)) { actualType = typeof(IDeprecated); } } bsonReader.ReturnToBookmark(bookmark); if (Config.AllowUpgradeFromBson && actualType.IsDeprecated() && !Config.TypesWithoutUpgrade.Contains(actualType)) { actualType = typeof(IDeprecated); } } return(actualType); }
protected virtual decimal readAmount(IBsonReader reader) { BsonMemberMap amountMap = _map.GetMemberMap(m => m.Amount); reader.ReadName(amountMap.ElementName); decimal amount; // support old numeric representations BsonType type = reader.GetCurrentBsonType(); switch (type) { case BsonType.Double: { double amountRead = reader.ReadDouble(); amount = Convert.ToDecimal(amountRead); break; } case BsonType.Decimal128: { Decimal128 amountRead = reader.ReadDecimal128(); amount = Decimal128.ToDecimal(amountRead); break; } case BsonType.String: { string amountRead = reader.ReadString(); amount = decimal.Parse(amountRead, CultureInfo.InvariantCulture); break; } default: var message = $"Cannot convert a {type} to a Decimal."; throw new NotSupportedException(message); } return(amount); }
public override TimeSpan Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args) { IBsonReader reader = context.Reader; BsonType bsonType = reader.GetCurrentBsonType(); switch (bsonType) { case BsonType.Null: reader.ReadNull(); return(TimeSpan.Zero); case BsonType.Int32: return(TimeSpan.FromMilliseconds((double)reader.ReadInt32())); case BsonType.Int64: return(TimeSpan.FromMilliseconds((double)reader.ReadInt64())); case BsonType.Double: return(TimeSpan.FromMilliseconds(reader.ReadDouble())); default: throw base.CreateCannotDeserializeFromBsonTypeException(bsonType); } }
// private methods private void ReadValue() { object jsonDotNetValue; switch (_wrappedReader.GetCurrentBsonType()) { case BsonType.Array: _wrappedReader.ReadStartArray(); SetCurrentToken(Newtonsoft.Json.JsonToken.StartArray); return; case BsonType.Binary: var bsonBinaryData = _wrappedReader.ReadBinaryData(); switch (bsonBinaryData.SubType) { case BsonBinarySubType.UuidLegacy: var guidRepresentation = GuidRepresentation.Unspecified; var bsonReader = _wrappedReader as BsonReader; if (bsonReader != null) { guidRepresentation = bsonReader.Settings.GuidRepresentation; } jsonDotNetValue = GuidConverter.FromBytes(bsonBinaryData.Bytes, guidRepresentation); break; case BsonBinarySubType.UuidStandard: jsonDotNetValue = GuidConverter.FromBytes(bsonBinaryData.Bytes, GuidRepresentation.Standard); break; default: jsonDotNetValue = bsonBinaryData.Bytes; break; } SetCurrentToken(Newtonsoft.Json.JsonToken.Bytes, jsonDotNetValue, bsonBinaryData); return; case BsonType.Boolean: var booleanValue = _wrappedReader.ReadBoolean(); SetCurrentToken(Newtonsoft.Json.JsonToken.Boolean, booleanValue, (BsonBoolean)booleanValue); return; case BsonType.DateTime: var bsonDateTime = new BsonDateTime(_wrappedReader.ReadDateTime()); if (bsonDateTime.IsValidDateTime) { jsonDotNetValue = bsonDateTime.ToUniversalTime(); } else { jsonDotNetValue = bsonDateTime.MillisecondsSinceEpoch; } SetCurrentToken(Newtonsoft.Json.JsonToken.Date, jsonDotNetValue, bsonDateTime); return; case BsonType.Document: _wrappedReader.ReadStartDocument(); SetCurrentToken(Newtonsoft.Json.JsonToken.StartObject); return; case BsonType.Double: var bsonDouble = new BsonDouble(_wrappedReader.ReadDouble()); switch (FloatParseHandling) { case Newtonsoft.Json.FloatParseHandling.Decimal: jsonDotNetValue = Convert.ToDecimal(bsonDouble); break; case Newtonsoft.Json.FloatParseHandling.Double: jsonDotNetValue = bsonDouble.Value; break; default: throw new NotSupportedException(string.Format("Unexpected FloatParseHandling value: {0}.", FloatParseHandling)); } SetCurrentToken(Newtonsoft.Json.JsonToken.Float, jsonDotNetValue, bsonDouble); return; case BsonType.Int32: var bsonInt32 = (BsonInt32)_wrappedReader.ReadInt32(); SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, (long)bsonInt32.Value, bsonInt32); return; case BsonType.Int64: var bsonInt64 = (BsonInt64)_wrappedReader.ReadInt64(); SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, bsonInt64.Value, bsonInt64); return; case BsonType.JavaScript: { var code = _wrappedReader.ReadJavaScript(); var bsonJavaScript = new BsonJavaScript(code); SetCurrentToken(Newtonsoft.Json.JsonToken.String, code, bsonJavaScript); } return; case BsonType.JavaScriptWithScope: { var code = _wrappedReader.ReadJavaScriptWithScope(); var context = BsonDeserializationContext.CreateRoot(_wrappedReader); var scope = BsonDocumentSerializer.Instance.Deserialize <BsonDocument>(context); var bsonJavaScriptWithScope = new BsonJavaScriptWithScope(code, scope); SetCurrentToken(Newtonsoft.Json.JsonToken.String, code, bsonJavaScriptWithScope); } return; case BsonType.MaxKey: _wrappedReader.ReadMaxKey(); SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonMaxKey.Value); return; case BsonType.MinKey: _wrappedReader.ReadMinKey(); SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonMinKey.Value); return; case BsonType.Null: _wrappedReader.ReadNull(); SetCurrentToken(Newtonsoft.Json.JsonToken.Null, null, BsonNull.Value); return; case BsonType.ObjectId: var bsonObjectId = new BsonObjectId(_wrappedReader.ReadObjectId()); SetCurrentToken(Newtonsoft.Json.JsonToken.Bytes, bsonObjectId.Value.ToByteArray(), bsonObjectId); return; case BsonType.RegularExpression: var bsonRegularExpression = _wrappedReader.ReadRegularExpression(); var pattern = bsonRegularExpression.Pattern; var options = bsonRegularExpression.Options; jsonDotNetValue = "/" + pattern.Replace("/", "\\/") + "/" + options; SetCurrentToken(Newtonsoft.Json.JsonToken.String, jsonDotNetValue, bsonRegularExpression); return; case BsonType.String: var stringValue = _wrappedReader.ReadString(); SetCurrentToken(Newtonsoft.Json.JsonToken.String, stringValue, (BsonString)stringValue); return; case BsonType.Symbol: var bsonSymbol = BsonSymbolTable.Lookup(_wrappedReader.ReadSymbol()); SetCurrentToken(Newtonsoft.Json.JsonToken.String, bsonSymbol.Name, bsonSymbol); return; case BsonType.Timestamp: var bsonTimestamp = new BsonTimestamp(_wrappedReader.ReadTimestamp()); SetCurrentToken(Newtonsoft.Json.JsonToken.Integer, bsonTimestamp.Value, bsonTimestamp); return; case BsonType.Undefined: _wrappedReader.ReadUndefined(); SetCurrentToken(Newtonsoft.Json.JsonToken.Undefined, null, BsonUndefined.Value); return; default: var message = string.Format("Unexpected BsonType: {0}.", _wrappedReader.GetCurrentBsonType()); throw new Newtonsoft.Json.JsonReaderException(message); } }
public static bool TryDeserializeToAny( this IBsonReader reader, IEnumerable <Type> nominalTypes, [MaybeNull] out object[] values ) { values = default; var success = false; // TODO: Prioritize primitives (including string), value types, then objects. var orderedTypes = nominalTypes .OrderBy(t => GetTypePriority(t)) .ToArray(); // Oddly enough BsonSerializer.Deserialize is fine with primitive // arrays but not arrays of documents. Go figure. if (reader.GetCurrentBsonType() == BsonType.Array) { var tempList = new List <object>(); success = true; reader.ReadStartArray(); while (reader.State != BsonReaderState.EndOfArray) { object?value = null; foreach (var nominalType in nominalTypes) { try { value = BsonSerializer.Deserialize( reader, nominalType ); break; } catch { } } if (value is null) { success = false; } else { tempList.Add(value); } } reader.ReadEndArray(); values = tempList.ToArray(); success = values.Any(); } else { values = new object[1]; foreach (var nominalType in nominalTypes) { try { values[0] = BsonSerializer.Deserialize( reader, nominalType ); success = true; break; } catch { } } } return(success); }
// 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 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); }
/***************************************************/ private object DeserializeDiscriminatedValue(BsonDeserializationContext context, BsonDeserializationArgs args) { // First try to recover the object type IBsonReader reader = context.Reader; BsonReaderBookmark bookmark = reader.GetBookmark(); Type actualType = typeof(CustomObject); try { actualType = _discriminatorConvention.GetActualType(reader, typeof(object)); } catch (Exception e) { BsonDocument doc = null; try { context.Reader.ReturnToBookmark(bookmark); IBsonSerializer bSerializer = BsonSerializer.LookupSerializer(typeof(BsonDocument)); doc = bSerializer.Deserialize(context, args) as BsonDocument; } catch { } if (doc != null && doc.Contains("_t") && doc["_t"].AsString == "DBNull") { return(null); } else { actualType = typeof(IDeprecated); } } context.Reader.ReturnToBookmark(bookmark); if (actualType == null) { return(null); } // Make sure the type is not deprecated if (Config.AllowUpgradeFromBson && actualType.IIsDeprecated() && !Config.TypesWithoutUpgrade.Contains(actualType)) { actualType = typeof(IDeprecated); } // Handle the special case where the type is object if (actualType == typeof(object)) { BsonType currentBsonType = reader.GetCurrentBsonType(); if (currentBsonType == BsonType.Document && context.DynamicDocumentSerializer != null) { return(context.DynamicDocumentSerializer.Deserialize(context, args)); } reader.ReadStartDocument(); reader.ReadEndDocument(); return(new object()); } // Handle the general case of finding the correct deserialiser and calling it try { IBsonSerializer bsonSerializer = BsonSerializer.LookupSerializer(actualType); if (bsonSerializer.GetType().Name == "EnumerableInterfaceImplementerSerializer`2" && context.Reader.CurrentBsonType == BsonType.Document) { if (!m_FallbackSerialisers.ContainsKey(actualType)) { CreateFallbackSerialiser(actualType); } bsonSerializer = m_FallbackSerialisers[actualType]; } return(bsonSerializer.Deserialize(context, args)); } catch (Exception e) { context.Reader.ReturnToBookmark(bookmark); if (e is FormatException && e.InnerException != null && (e.InnerException is FormatException || e.InnerException is BsonSerializationException)) { // A child of the object is causing problems. Try to recover from custom object IBsonSerializer customSerializer = BsonSerializer.LookupSerializer(typeof(CustomObject)); object result = customSerializer.Deserialize(context, args); Guid objectId = ((CustomObject)result).BHoM_Guid; if (!Config.TypesWithoutUpgrade.Contains(actualType)) { if (m_StackCounter.ContainsKey(objectId)) { m_StackCounter[objectId] += 1; } else { m_StackCounter[objectId] = 1; } if (m_StackCounter[objectId] < 10) { result = Convert.FromBson(result.ToBson()); m_StackCounter.Remove(objectId); } } if (result is CustomObject) { Engine.Reflection.Compute.RecordWarning("The type " + actualType.FullName + " is unknown -> data returned as custom objects."); Config.TypesWithoutUpgrade.Add(actualType); } return(result); } else if (actualType != typeof(IDeprecated)) { // Try the deprecated object serialiser IBsonSerializer deprecatedSerializer = BsonSerializer.LookupSerializer(typeof(IDeprecated)); return(deprecatedSerializer.Deserialize(context, args)); } else { // Last resort: just return the custom object Engine.Reflection.Compute.RecordWarning("The type " + actualType.FullName + " is unknown -> data returned as custom objects."); IBsonSerializer customSerializer = BsonSerializer.LookupSerializer(typeof(CustomObject)); return(customSerializer.Deserialize(context, args)); } } }
/***************************************************/ private object DeserializeDiscriminatedValue(BsonDeserializationContext context, BsonDeserializationArgs args) { // First try to recover the object type IBsonReader reader = context.Reader; BsonReaderBookmark bookmark = reader.GetBookmark(); Type actualType = typeof(CustomObject); try { actualType = _discriminatorConvention.GetActualType(reader, typeof(object)); } catch { // This is were we can call the Version_Engine to return the new type string from the old one if exists string recordedType = GetCurrentTypeValue(reader); // If failed, return Custom object context.Reader.ReturnToBookmark(bookmark); Engine.Reflection.Compute.RecordWarning("The type " + recordedType + " is unknown -> data returned as custom objects."); IBsonSerializer customSerializer = BsonSerializer.LookupSerializer(typeof(CustomObject)); return(customSerializer.Deserialize(context, args)); } // Handle the special case where the type is object if (actualType == typeof(object)) { BsonType currentBsonType = reader.GetCurrentBsonType(); if (currentBsonType == BsonType.Document && context.DynamicDocumentSerializer != null) { return(context.DynamicDocumentSerializer.Deserialize(context, args)); } reader.ReadStartDocument(); reader.ReadEndDocument(); return(new object()); } // Handle the genral case of finding the correct deserialiser and calling it IBsonSerializer bsonSerializer = BsonSerializer.LookupSerializer(actualType); IBsonPolymorphicSerializer bsonPolymorphicSerializer = bsonSerializer as IBsonPolymorphicSerializer; if (bsonPolymorphicSerializer != null && bsonPolymorphicSerializer.IsDiscriminatorCompatibleWithObjectSerializer) { bookmark = context.Reader.GetBookmark(); try { return(bsonSerializer.Deserialize(context, args)); } catch { context.Reader.ReturnToBookmark(bookmark); Engine.Reflection.Compute.RecordWarning("Cannot find a definition of type " + actualType.FullName + " that matches the object to deserialise -> data returned as custom objects."); IBsonSerializer customSerializer = BsonSerializer.LookupSerializer(typeof(CustomObject)); CustomObject fallback = customSerializer.Deserialize(context, args) as CustomObject; //This is where we will try to get the correct object type from the custom object using the versionning engine // If failed, just return the custom object return(fallback); } } object result = null; bool flag = false; reader.ReadStartDocument(); while (reader.ReadBsonType() != 0) { string text = reader.ReadName(); if (text == _discriminatorConvention.ElementName) { reader.SkipValue(); } else { if (!(text == "_v")) { throw new FormatException($"Unexpected element name: '{text}'."); } result = bsonSerializer.Deserialize(context); flag = true; } } reader.ReadEndDocument(); if (!flag) { throw new FormatException("_v element missing."); } return(result); }
/***************************************************/ private object DeserializeDiscriminatedValue(BsonDeserializationContext context, BsonDeserializationArgs args) { // First try to recover the object type IBsonReader reader = context.Reader; BsonReaderBookmark bookmark = reader.GetBookmark(); Type actualType = typeof(CustomObject); try { actualType = _discriminatorConvention.GetActualType(reader, typeof(object)); } catch { try { context.Reader.ReturnToBookmark(bookmark); DeprecatedSerializer deprecatedSerialiser = new DeprecatedSerializer(); return(deprecatedSerialiser.Deserialize(context, args)); } catch { } } context.Reader.ReturnToBookmark(bookmark); if (actualType == null) { return(null); } // Handle the special case where the type is object if (actualType == typeof(object)) { BsonType currentBsonType = reader.GetCurrentBsonType(); if (currentBsonType == BsonType.Document && context.DynamicDocumentSerializer != null) { return(context.DynamicDocumentSerializer.Deserialize(context, args)); } reader.ReadStartDocument(); reader.ReadEndDocument(); return(new object()); } // Handle the general case of finding the correct deserialiser and calling it try { if (!BsonClassMap.IsClassMapRegistered(actualType)) { Compute.RegisterClassMap(actualType); // LookupSerializer creates the classMap if it doesn't exist so important to do it through our own method } IBsonSerializer bsonSerializer = BsonSerializer.LookupSerializer(actualType); if (bsonSerializer.GetType().Name == "EnumerableInterfaceImplementerSerializer`2" && context.Reader.CurrentBsonType == BsonType.Document) { if (!m_FallbackSerialisers.ContainsKey(actualType)) { CreateFallbackSerialiser(actualType); } bsonSerializer = m_FallbackSerialisers[actualType]; } else if (actualType.Name == "Dictionary`2" && context.Reader.CurrentBsonType == BsonType.Document) { DictionarySerializer dicSerialiser = new DictionarySerializer(); return(dicSerialiser.Deserialize(context, args)); } return(bsonSerializer.Deserialize(context, args)); } catch (Exception e) { if (e.Message.Contains("Could not load file or assembly")) { Engine.Reflection.Compute.RecordError(e.Message); } context.Reader.ReturnToBookmark(bookmark); DeprecatedSerializer deprecatedSerialiser = new DeprecatedSerializer(); return(deprecatedSerialiser.Deserialize(context, args)); } }