/// <inheritdoc /> public override ISerializer BuildSerializer( SerializerRepresentation serializerRepresentation, AssemblyMatchStrategy assemblyMatchStrategy = AssemblyMatchStrategy.AnySingleVersion) { if (serializerRepresentation == null) { throw new ArgumentNullException(nameof(serializerRepresentation)); } // ReSharper disable once RedundantArgumentDefaultValue var configurationType = serializerRepresentation.SerializationConfigType?.ResolveFromLoadedTypes(assemblyMatchStrategy, throwIfCannotResolve: true); ISerializer serializer; switch (serializerRepresentation.SerializationKind) { case SerializationKind.Bson: serializer = new ObcBsonSerializer(configurationType?.ToBsonSerializationConfigurationType()); break; default: throw new NotSupportedException(Invariant($"{nameof(serializerRepresentation)} from enumeration {nameof(SerializationKind)} of {serializerRepresentation.SerializationKind} is not supported.")); } var result = this.WrapInCompressingSerializerIfAppropriate(serializer, serializerRepresentation.CompressionKind); return(result); }
/// <inheritdoc /> public Type GetActualType( IBsonReader bsonReader, Type nominalType) { if (bsonReader == null) { throw new ArgumentNullException(nameof(bsonReader)); } if (nominalType == null) { throw new ArgumentNullException(nameof(nominalType)); } var bookmark = bsonReader.GetBookmark(); bsonReader.ReadStartDocument(); Type result; if (bsonReader.FindElement(this.ElementName)) { var value = bsonReader.ReadString(); try { result = value.ResolveFromLoadedTypes(); if (result == null) { throw new InvalidOperationException(Invariant($"'{nameof(result)}' is null")); } } catch (ArgumentException) { bsonReader.ReturnToBookmark(bookmark); // previously persisted documents will have used Type.Name // in that case ToTypeRepresentationFromAssemblyQualifiedName will throw. // this is here for backward compatibility. result = HierarchicalDiscriminatorConvention.GetActualType(bsonReader, nominalType); if (result == null) { throw new InvalidOperationException(Invariant($"Found discriminator '{value}' when deserializing into {nameof(nominalType)} '{nominalType.ToStringReadable()}', but could not get the actual type using {nameof(TypeNameDiscriminator)}.{nameof(TypeNameDiscriminator.GetActualType)}(); it returned null.")); } } } else { // if _t is not in the payload then a discriminator wasn't needed result = nominalType; } bsonReader.ReturnToBookmark(bookmark); // See notes in ThrowOnUnregisteredTypeIfAppropriate for the need to make this call. // Note that this is a sub-par solution. Ideally this discriminator would know // which serializer (and hence which serialization configuration) is being used for deserializing, // because it is passed as a parameter to this method. Because that's not an option in Mongo, // we have to use ObcBsonSerializer.SerializationConfigurationInUseForDeserialization, which // tracks the thread being used for the deserialize operation and associates the serialization // configuration in-use with the thread. var serializationConfiguration = ObcBsonSerializer.GetSerializationConfigurationInUseForDeserialization(); // serializationConfiguration is only ever null if the consumer is NOT using the front-door for serialization // (i.e. a serializer), but using the Mongo driver directly to deserialize. In that case, we do not know // which serialization configuration is "in use". serializationConfiguration?.ThrowOnUnregisteredTypeIfAppropriate(result, SerializationDirection.Deserialize, null); return(result); }