示例#1
0
        /// <summary>
        /// Builds a <see cref="TypeToRegisterForBson"/> for a type using the most sensible settings,
        /// with a specified <see cref="IStringSerializeAndDeserialize"/> to use everywhere the type appears.
        /// </summary>
        /// <param name="type">The type to register.</param>
        /// <param name="stringSerializer">The string serializer to use for <paramref name="type"/>.</param>
        /// <returns>
        /// The type to register for BSON serialization.
        /// </returns>
        public static TypeToRegisterForBson ToTypeToRegisterForBsonUsingStringSerializer(
            this Type type,
            IStringSerializeAndDeserialize stringSerializer)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (stringSerializer == null)
            {
                throw new ArgumentNullException(nameof(stringSerializer));
            }

            var serializer = StringSerializerBackedBsonSerializer.Build(type, stringSerializer);

            IBsonSerializer BsonSerializerBuilderFunc() => serializer;

            var bsonSerializerBuilder = new BsonSerializerBuilder(BsonSerializerBuilderFunc, BsonSerializerOutputKind.String);

            var result = new TypeToRegisterForBson(type, MemberTypesToInclude.None, RelatedTypesToInclude.Default, bsonSerializerBuilder, null);

            return(result);
        }
示例#2
0
        /// <summary>
        /// Gets the serializer to use for a given type.
        /// </summary>
        /// <param name="type">The type to serialize.</param>
        /// <param name="defaultToObjectSerializer">If true, then returns <see cref="ObjectSerializer"/> when the serializer cannot be determined.  Otherwise, returns null.</param>
        /// <returns>
        /// The serializer to use for the specified type.
        /// </returns>
        public static IBsonSerializer GetAppropriateSerializer(
            this Type type,
            bool defaultToObjectSerializer)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            IBsonSerializer result;

            if (type == typeof(string))
            {
                result = new StringSerializer();
            }
            else if (type == typeof(Guid))
            {
                result = new GuidSerializer();
            }
            else if (type.IsEnum)
            {
                result = typeof(EnumStringBsonSerializer <>).MakeGenericType(type).Construct <IBsonSerializer>();
            }
            else if (type.IsClosedNullableType())
            {
                result = typeof(NullableBsonSerializer <>).MakeGenericType(Nullable.GetUnderlyingType(type)).Construct <IBsonSerializer>();
            }
            else if (type == typeof(DateTime))
            {
                result = new StringSerializerBackedBsonSerializer <DateTime>(DateTimeStringSerializer);
            }
            else if (type.IsClosedSystemDictionaryType())
            {
                var keyType = type.GetClosedSystemDictionaryKeyType();

                var valueType = type.GetClosedSystemDictionaryValueType();

                // It very much seems like defaultToObjectSerializer should be false, consistent with
                // what we do for array and collection elements.  However, unit tests fail when we change to false.
                // We are not sure why and need to dig-in in the future.  We do know that using ObjectSerializer
                // still allows for dictionary keys and values to use a custom/registered serializer.
                var keySerializer = GetAppropriateSerializer(keyType, defaultToObjectSerializer: true);

                var valueSerializer = GetAppropriateSerializer(valueType, defaultToObjectSerializer: true);

                result = typeof(DictionaryBsonSerializer <, ,>).MakeGenericType(type, keyType, valueType).Construct <IBsonSerializer>(DictionaryRepresentation.ArrayOfDocuments, keySerializer, valueSerializer);
            }
            else if (type.IsArray)
            {
                var elementType = type.GetElementType();

                // Don't default to ObjectSerializer because if there is no element serializer we want BSON to find
                // an existing registered serializer or fallback to the registered class map for the type.
                var elementSerializer = GetAppropriateSerializer(elementType, defaultToObjectSerializer: false);

                result = elementSerializer == null
                    ? typeof(ArraySerializer <>).MakeGenericType(elementType).Construct <IBsonSerializer>()
                    : typeof(ArraySerializer <>).MakeGenericType(elementType).Construct <IBsonSerializer>(elementSerializer);
            }
            else if (type.IsClosedSystemCollectionType())
            {
                var elementType = type.GetClosedSystemCollectionElementType();

                // Don't default to ObjectSerializer because if there is no element serializer we want BSON to find
                // an existing registered serializer or fallback to the registered class map for the type.
                var elementSerializer = GetAppropriateSerializer(elementType, defaultToObjectSerializer: false);

                result = typeof(CollectionBsonSerializer <,>).MakeGenericType(type, elementType).Construct <IBsonSerializer>(elementSerializer);
            }
            else
            {
                result = defaultToObjectSerializer ? new ObjectSerializer() : null;
            }

            return(result);
        }