Example #1
0
        /// <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);
        }