| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- /* Copyright 2010-2014 MongoDB Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Globalization;
- using System.Net;
- using MongoDB.Bson.Serialization.Serializers;
- namespace MongoDB.Bson.Serialization
- {
- /// <summary>
- /// Represents the default serialization provider.
- /// </summary>
- internal class BsonDefaultSerializationProvider : IBsonSerializationProvider
- {
- // private static fields
- private static Dictionary<Type, Type> __serializers;
- private static Dictionary<Type, Type> __genericSerializerDefinitions;
- // static constructor
- static BsonDefaultSerializationProvider()
- {
- __serializers = new Dictionary<Type, Type>
- {
- { typeof(BitArray), typeof(BitArraySerializer) },
- { typeof(Boolean), typeof(BooleanSerializer) },
- { typeof(BsonArray), typeof(BsonArraySerializer) },
- { typeof(BsonBinaryData), typeof(BsonBinaryDataSerializer) },
- { typeof(BsonBoolean), typeof(BsonBooleanSerializer) },
- { typeof(BsonDateTime), typeof(BsonDateTimeSerializer) },
- { typeof(BsonDocument), typeof(BsonDocumentSerializer) },
- { typeof(BsonDocumentWrapper), typeof(BsonDocumentWrapperSerializer) },
- { typeof(BsonDouble), typeof(BsonDoubleSerializer) },
- { typeof(BsonInt32), typeof(BsonInt32Serializer) },
- { typeof(BsonInt64), typeof(BsonInt64Serializer) },
- { typeof(BsonJavaScript), typeof(BsonJavaScriptSerializer) },
- { typeof(BsonJavaScriptWithScope), typeof(BsonJavaScriptWithScopeSerializer) },
- { typeof(BsonMaxKey), typeof(BsonMaxKeySerializer) },
- { typeof(BsonMinKey), typeof(BsonMinKeySerializer) },
- { typeof(BsonNull), typeof(BsonNullSerializer) },
- { typeof(BsonObjectId), typeof(BsonObjectIdSerializer) },
- { typeof(BsonRegularExpression), typeof(BsonRegularExpressionSerializer) },
- { typeof(BsonString), typeof(BsonStringSerializer) },
- { typeof(BsonSymbol), typeof(BsonSymbolSerializer) },
- { typeof(BsonTimestamp), typeof(BsonTimestampSerializer) },
- { typeof(BsonUndefined), typeof(BsonUndefinedSerializer) },
- { typeof(BsonValue), typeof(BsonValueSerializer) },
- { typeof(Byte), typeof(ByteSerializer) },
- { typeof(Byte[]), typeof(ByteArraySerializer) },
- { typeof(Char), typeof(CharSerializer) },
- { typeof(CultureInfo), typeof(CultureInfoSerializer) },
- { typeof(DateTime), typeof(DateTimeSerializer) },
- { typeof(DateTimeOffset), typeof(DateTimeOffsetSerializer) },
- { typeof(Decimal), typeof(DecimalSerializer) },
- { typeof(Double), typeof(DoubleSerializer) },
- { typeof(Guid), typeof(GuidSerializer) },
- { typeof(Int16), typeof(Int16Serializer) },
- { typeof(Int32), typeof(Int32Serializer) },
- { typeof(Int64), typeof(Int64Serializer) },
- { typeof(IPAddress), typeof(IPAddressSerializer) },
- { typeof(IPEndPoint), typeof(IPEndPointSerializer) },
- { typeof(Object), typeof(ObjectSerializer) },
- { typeof(ObjectId), typeof(ObjectIdSerializer) },
- { typeof(Queue), typeof(QueueSerializer) },
- { typeof(SByte), typeof(SByteSerializer) },
- { typeof(Single), typeof(SingleSerializer) },
- { typeof(Stack), typeof(StackSerializer) },
- { typeof(String), typeof(StringSerializer) },
- { typeof(TimeSpan), typeof(TimeSpanSerializer) },
- { typeof(UInt16), typeof(UInt16Serializer) },
- { typeof(UInt32), typeof(UInt32Serializer) },
- { typeof(UInt64), typeof(UInt64Serializer) },
- { typeof(Uri), typeof(UriSerializer) },
- { typeof(Version), typeof(VersionSerializer) }
- };
- __genericSerializerDefinitions = new Dictionary<Type, Type>
- {
- { typeof(KeyValuePair<,>), typeof(KeyValuePairSerializer<,>) },
- { typeof(Nullable<>), typeof(NullableSerializer<>) },
- { typeof(Queue<>), typeof(QueueSerializer<>) },
- { typeof(Stack<>), typeof(StackSerializer<>) }
- };
- }
- // constructors
- /// <summary>
- /// Initializes a new instance of the BsonDefaultSerializer class.
- /// </summary>
- public BsonDefaultSerializationProvider()
- {
- }
- // public methods
- /// <summary>
- /// Gets the serializer for a type.
- /// </summary>
- /// <param name="type">The type.</param>
- /// <returns>The serializer.</returns>
- public IBsonSerializer GetSerializer(Type type)
- {
- Type serializerType;
- if (__serializers.TryGetValue(type, out serializerType))
- {
- return (IBsonSerializer)Activator.CreateInstance(serializerType);
- }
- // use BsonDocumentSerializer for all subclasses of BsonDocument also
- if (typeof(BsonDocument).IsAssignableFrom(type))
- {
- return BsonDocumentSerializer.Instance;
- }
- // use BsonIBsonSerializableSerializer for all classes that implement IBsonSerializable
- if (typeof(IBsonSerializable).IsAssignableFrom(type))
- {
- return BsonIBsonSerializableSerializer.Instance;
- }
- if (type.IsGenericType)
- {
- var genericTypeDefinition = type.GetGenericTypeDefinition();
- Type genericSerializerDefinition;
- if (__genericSerializerDefinitions.TryGetValue(genericTypeDefinition, out genericSerializerDefinition))
- {
- var genericSerializerType = genericSerializerDefinition.MakeGenericType(type.GetGenericArguments());
- return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
- }
- }
- if (type.IsArray)
- {
- var elementType = type.GetElementType();
- switch (type.GetArrayRank())
- {
- case 1:
- var arraySerializerDefinition = typeof(ArraySerializer<>);
- var arraySerializerType = arraySerializerDefinition.MakeGenericType(elementType);
- return (IBsonSerializer)Activator.CreateInstance(arraySerializerType);
- case 2:
- var twoDimensionalArraySerializerDefinition = typeof(TwoDimensionalArraySerializer<>);
- var twoDimensionalArraySerializerType = twoDimensionalArraySerializerDefinition.MakeGenericType(elementType);
- return (IBsonSerializer)Activator.CreateInstance(twoDimensionalArraySerializerType);
- case 3:
- var threeDimensionalArraySerializerDefinition = typeof(ThreeDimensionalArraySerializer<>);
- var threeDimensionalArraySerializerType = threeDimensionalArraySerializerDefinition.MakeGenericType(elementType);
- return (IBsonSerializer)Activator.CreateInstance(threeDimensionalArraySerializerType);
- default:
- var message = string.Format("No serializer found for array for rank {0}.", type.GetArrayRank());
- throw new BsonSerializationException(message);
- }
- }
- if (type.IsEnum)
- {
- return new EnumSerializer();
- }
- // classes that implement IDictionary or IEnumerable are serialized using either DictionarySerializer or EnumerableSerializer
- // this does mean that any additional public properties the class might have won't be serialized (just like the XmlSerializer)
- var collectionSerializer = GetCollectionSerializer(type);
- if (collectionSerializer != null)
- {
- return collectionSerializer;
- }
- // we'll try our best by attempting to find a discriminator hoping it points
- // us to a concrete type with a serializer.
- if (type.IsInterface)
- {
- return InterfaceSerializer.Instance;
- }
- return null;
- }
- // private methods
- private IBsonSerializer GetCollectionSerializer(Type type)
- {
- Type implementedGenericDictionaryInterface = null;
- Type implementedGenericEnumerableInterface = null;
- Type implementedDictionaryInterface = null;
- Type implementedEnumerableInterface = null;
- var implementedInterfaces = new List<Type>(type.GetInterfaces());
- if (type.IsInterface)
- {
- implementedInterfaces.Add(type);
- }
- foreach (var implementedInterface in implementedInterfaces)
- {
- if (implementedInterface.IsGenericType)
- {
- var genericInterfaceDefinition = implementedInterface.GetGenericTypeDefinition();
- if (genericInterfaceDefinition == typeof(IDictionary<,>))
- {
- implementedGenericDictionaryInterface = implementedInterface;
- }
- if (genericInterfaceDefinition == typeof(IEnumerable<>))
- {
- implementedGenericEnumerableInterface = implementedInterface;
- }
- }
- else
- {
- if (implementedInterface == typeof(IDictionary))
- {
- implementedDictionaryInterface = implementedInterface;
- }
- if (implementedInterface == typeof(IEnumerable))
- {
- implementedEnumerableInterface = implementedInterface;
- }
- }
- }
- // the order of the tests is important
- if (implementedGenericDictionaryInterface != null)
- {
- var keyType = implementedGenericDictionaryInterface.GetGenericArguments()[0];
- var valueType = implementedGenericDictionaryInterface.GetGenericArguments()[1];
- var genericSerializerDefinition = typeof(DictionarySerializer<,>);
- var genericSerializerType = genericSerializerDefinition.MakeGenericType(keyType, valueType);
- return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
- }
- else if (implementedDictionaryInterface != null)
- {
- return new DictionarySerializer();
- }
- else if (implementedGenericEnumerableInterface != null)
- {
- var valueType = implementedGenericEnumerableInterface.GetGenericArguments()[0];
- var readOnlyCollectionType = typeof(ReadOnlyCollection<>).MakeGenericType(valueType);
- Type genericSerializerDefinition;
- if (readOnlyCollectionType.IsAssignableFrom(type))
- {
- genericSerializerDefinition = typeof(ReadOnlyCollectionSerializer<>);
- if (type != readOnlyCollectionType)
- {
- BsonSerializer.RegisterDiscriminator(type, type.Name);
- }
- }
- else
- {
- genericSerializerDefinition = typeof(EnumerableSerializer<>);
- }
- var genericSerializerType = genericSerializerDefinition.MakeGenericType(valueType);
- return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
- }
- else if (implementedEnumerableInterface != null)
- {
- return new EnumerableSerializer();
- }
- return null;
- }
- }
- }
|