BsonDefaultSerializationProvider.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /* Copyright 2010-2014 MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.Collections;
  17. using System.Collections.Generic;
  18. using System.Collections.ObjectModel;
  19. using System.Globalization;
  20. using System.Net;
  21. using MongoDB.Bson.Serialization.Serializers;
  22. namespace MongoDB.Bson.Serialization
  23. {
  24. /// <summary>
  25. /// Represents the default serialization provider.
  26. /// </summary>
  27. internal class BsonDefaultSerializationProvider : IBsonSerializationProvider
  28. {
  29. // private static fields
  30. private static Dictionary<Type, Type> __serializers;
  31. private static Dictionary<Type, Type> __genericSerializerDefinitions;
  32. // static constructor
  33. static BsonDefaultSerializationProvider()
  34. {
  35. __serializers = new Dictionary<Type, Type>
  36. {
  37. { typeof(BitArray), typeof(BitArraySerializer) },
  38. { typeof(Boolean), typeof(BooleanSerializer) },
  39. { typeof(BsonArray), typeof(BsonArraySerializer) },
  40. { typeof(BsonBinaryData), typeof(BsonBinaryDataSerializer) },
  41. { typeof(BsonBoolean), typeof(BsonBooleanSerializer) },
  42. { typeof(BsonDateTime), typeof(BsonDateTimeSerializer) },
  43. { typeof(BsonDocument), typeof(BsonDocumentSerializer) },
  44. { typeof(BsonDocumentWrapper), typeof(BsonDocumentWrapperSerializer) },
  45. { typeof(BsonDouble), typeof(BsonDoubleSerializer) },
  46. { typeof(BsonInt32), typeof(BsonInt32Serializer) },
  47. { typeof(BsonInt64), typeof(BsonInt64Serializer) },
  48. { typeof(BsonJavaScript), typeof(BsonJavaScriptSerializer) },
  49. { typeof(BsonJavaScriptWithScope), typeof(BsonJavaScriptWithScopeSerializer) },
  50. { typeof(BsonMaxKey), typeof(BsonMaxKeySerializer) },
  51. { typeof(BsonMinKey), typeof(BsonMinKeySerializer) },
  52. { typeof(BsonNull), typeof(BsonNullSerializer) },
  53. { typeof(BsonObjectId), typeof(BsonObjectIdSerializer) },
  54. { typeof(BsonRegularExpression), typeof(BsonRegularExpressionSerializer) },
  55. { typeof(BsonString), typeof(BsonStringSerializer) },
  56. { typeof(BsonSymbol), typeof(BsonSymbolSerializer) },
  57. { typeof(BsonTimestamp), typeof(BsonTimestampSerializer) },
  58. { typeof(BsonUndefined), typeof(BsonUndefinedSerializer) },
  59. { typeof(BsonValue), typeof(BsonValueSerializer) },
  60. { typeof(Byte), typeof(ByteSerializer) },
  61. { typeof(Byte[]), typeof(ByteArraySerializer) },
  62. { typeof(Char), typeof(CharSerializer) },
  63. { typeof(CultureInfo), typeof(CultureInfoSerializer) },
  64. { typeof(DateTime), typeof(DateTimeSerializer) },
  65. { typeof(DateTimeOffset), typeof(DateTimeOffsetSerializer) },
  66. { typeof(Decimal), typeof(DecimalSerializer) },
  67. { typeof(Double), typeof(DoubleSerializer) },
  68. { typeof(Guid), typeof(GuidSerializer) },
  69. { typeof(Int16), typeof(Int16Serializer) },
  70. { typeof(Int32), typeof(Int32Serializer) },
  71. { typeof(Int64), typeof(Int64Serializer) },
  72. { typeof(IPAddress), typeof(IPAddressSerializer) },
  73. { typeof(IPEndPoint), typeof(IPEndPointSerializer) },
  74. { typeof(Object), typeof(ObjectSerializer) },
  75. { typeof(ObjectId), typeof(ObjectIdSerializer) },
  76. { typeof(Queue), typeof(QueueSerializer) },
  77. { typeof(SByte), typeof(SByteSerializer) },
  78. { typeof(Single), typeof(SingleSerializer) },
  79. { typeof(Stack), typeof(StackSerializer) },
  80. { typeof(String), typeof(StringSerializer) },
  81. { typeof(TimeSpan), typeof(TimeSpanSerializer) },
  82. { typeof(UInt16), typeof(UInt16Serializer) },
  83. { typeof(UInt32), typeof(UInt32Serializer) },
  84. { typeof(UInt64), typeof(UInt64Serializer) },
  85. { typeof(Uri), typeof(UriSerializer) },
  86. { typeof(Version), typeof(VersionSerializer) }
  87. };
  88. __genericSerializerDefinitions = new Dictionary<Type, Type>
  89. {
  90. { typeof(KeyValuePair<,>), typeof(KeyValuePairSerializer<,>) },
  91. { typeof(Nullable<>), typeof(NullableSerializer<>) },
  92. { typeof(Queue<>), typeof(QueueSerializer<>) },
  93. { typeof(Stack<>), typeof(StackSerializer<>) }
  94. };
  95. }
  96. // constructors
  97. /// <summary>
  98. /// Initializes a new instance of the BsonDefaultSerializer class.
  99. /// </summary>
  100. public BsonDefaultSerializationProvider()
  101. {
  102. }
  103. // public methods
  104. /// <summary>
  105. /// Gets the serializer for a type.
  106. /// </summary>
  107. /// <param name="type">The type.</param>
  108. /// <returns>The serializer.</returns>
  109. public IBsonSerializer GetSerializer(Type type)
  110. {
  111. Type serializerType;
  112. if (__serializers.TryGetValue(type, out serializerType))
  113. {
  114. return (IBsonSerializer)Activator.CreateInstance(serializerType);
  115. }
  116. // use BsonDocumentSerializer for all subclasses of BsonDocument also
  117. if (typeof(BsonDocument).IsAssignableFrom(type))
  118. {
  119. return BsonDocumentSerializer.Instance;
  120. }
  121. // use BsonIBsonSerializableSerializer for all classes that implement IBsonSerializable
  122. if (typeof(IBsonSerializable).IsAssignableFrom(type))
  123. {
  124. return BsonIBsonSerializableSerializer.Instance;
  125. }
  126. if (type.IsGenericType)
  127. {
  128. var genericTypeDefinition = type.GetGenericTypeDefinition();
  129. Type genericSerializerDefinition;
  130. if (__genericSerializerDefinitions.TryGetValue(genericTypeDefinition, out genericSerializerDefinition))
  131. {
  132. var genericSerializerType = genericSerializerDefinition.MakeGenericType(type.GetGenericArguments());
  133. return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
  134. }
  135. }
  136. if (type.IsArray)
  137. {
  138. var elementType = type.GetElementType();
  139. switch (type.GetArrayRank())
  140. {
  141. case 1:
  142. var arraySerializerDefinition = typeof(ArraySerializer<>);
  143. var arraySerializerType = arraySerializerDefinition.MakeGenericType(elementType);
  144. return (IBsonSerializer)Activator.CreateInstance(arraySerializerType);
  145. case 2:
  146. var twoDimensionalArraySerializerDefinition = typeof(TwoDimensionalArraySerializer<>);
  147. var twoDimensionalArraySerializerType = twoDimensionalArraySerializerDefinition.MakeGenericType(elementType);
  148. return (IBsonSerializer)Activator.CreateInstance(twoDimensionalArraySerializerType);
  149. case 3:
  150. var threeDimensionalArraySerializerDefinition = typeof(ThreeDimensionalArraySerializer<>);
  151. var threeDimensionalArraySerializerType = threeDimensionalArraySerializerDefinition.MakeGenericType(elementType);
  152. return (IBsonSerializer)Activator.CreateInstance(threeDimensionalArraySerializerType);
  153. default:
  154. var message = string.Format("No serializer found for array for rank {0}.", type.GetArrayRank());
  155. throw new BsonSerializationException(message);
  156. }
  157. }
  158. if (type.IsEnum)
  159. {
  160. return new EnumSerializer();
  161. }
  162. // classes that implement IDictionary or IEnumerable are serialized using either DictionarySerializer or EnumerableSerializer
  163. // this does mean that any additional public properties the class might have won't be serialized (just like the XmlSerializer)
  164. var collectionSerializer = GetCollectionSerializer(type);
  165. if (collectionSerializer != null)
  166. {
  167. return collectionSerializer;
  168. }
  169. // we'll try our best by attempting to find a discriminator hoping it points
  170. // us to a concrete type with a serializer.
  171. if (type.IsInterface)
  172. {
  173. return InterfaceSerializer.Instance;
  174. }
  175. return null;
  176. }
  177. // private methods
  178. private IBsonSerializer GetCollectionSerializer(Type type)
  179. {
  180. Type implementedGenericDictionaryInterface = null;
  181. Type implementedGenericEnumerableInterface = null;
  182. Type implementedDictionaryInterface = null;
  183. Type implementedEnumerableInterface = null;
  184. var implementedInterfaces = new List<Type>(type.GetInterfaces());
  185. if (type.IsInterface)
  186. {
  187. implementedInterfaces.Add(type);
  188. }
  189. foreach (var implementedInterface in implementedInterfaces)
  190. {
  191. if (implementedInterface.IsGenericType)
  192. {
  193. var genericInterfaceDefinition = implementedInterface.GetGenericTypeDefinition();
  194. if (genericInterfaceDefinition == typeof(IDictionary<,>))
  195. {
  196. implementedGenericDictionaryInterface = implementedInterface;
  197. }
  198. if (genericInterfaceDefinition == typeof(IEnumerable<>))
  199. {
  200. implementedGenericEnumerableInterface = implementedInterface;
  201. }
  202. }
  203. else
  204. {
  205. if (implementedInterface == typeof(IDictionary))
  206. {
  207. implementedDictionaryInterface = implementedInterface;
  208. }
  209. if (implementedInterface == typeof(IEnumerable))
  210. {
  211. implementedEnumerableInterface = implementedInterface;
  212. }
  213. }
  214. }
  215. // the order of the tests is important
  216. if (implementedGenericDictionaryInterface != null)
  217. {
  218. var keyType = implementedGenericDictionaryInterface.GetGenericArguments()[0];
  219. var valueType = implementedGenericDictionaryInterface.GetGenericArguments()[1];
  220. var genericSerializerDefinition = typeof(DictionarySerializer<,>);
  221. var genericSerializerType = genericSerializerDefinition.MakeGenericType(keyType, valueType);
  222. return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
  223. }
  224. else if (implementedDictionaryInterface != null)
  225. {
  226. return new DictionarySerializer();
  227. }
  228. else if (implementedGenericEnumerableInterface != null)
  229. {
  230. var valueType = implementedGenericEnumerableInterface.GetGenericArguments()[0];
  231. var readOnlyCollectionType = typeof(ReadOnlyCollection<>).MakeGenericType(valueType);
  232. Type genericSerializerDefinition;
  233. if (readOnlyCollectionType.IsAssignableFrom(type))
  234. {
  235. genericSerializerDefinition = typeof(ReadOnlyCollectionSerializer<>);
  236. if (type != readOnlyCollectionType)
  237. {
  238. BsonSerializer.RegisterDiscriminator(type, type.Name);
  239. }
  240. }
  241. else
  242. {
  243. genericSerializerDefinition = typeof(EnumerableSerializer<>);
  244. }
  245. var genericSerializerType = genericSerializerDefinition.MakeGenericType(valueType);
  246. return (IBsonSerializer)Activator.CreateInstance(genericSerializerType);
  247. }
  248. else if (implementedEnumerableInterface != null)
  249. {
  250. return new EnumerableSerializer();
  251. }
  252. return null;
  253. }
  254. }
  255. }