CollectionsSerializationProvider.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* Copyright 2010-2016 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.Dynamic;
  20. using System.Reflection;
  21. using MongoDB.Bson.Serialization.Serializers;
  22. namespace MongoDB.Bson.Serialization
  23. {
  24. /// <summary>
  25. /// Provides serializers for collections.
  26. /// </summary>
  27. public class CollectionsSerializationProvider : BsonSerializationProviderBase
  28. {
  29. private static readonly Dictionary<Type, Type> __serializerTypes;
  30. static CollectionsSerializationProvider()
  31. {
  32. __serializerTypes = new Dictionary<Type, Type>
  33. {
  34. { typeof(BitArray), typeof(BitArraySerializer) },
  35. { typeof(ExpandoObject), typeof(ExpandoObjectSerializer) },
  36. { typeof(Queue), typeof(QueueSerializer) },
  37. { typeof(Stack), typeof(StackSerializer) },
  38. { typeof(Queue<>), typeof(QueueSerializer<>) },
  39. { typeof(ReadOnlyCollection<>), typeof(ReadOnlyCollectionSerializer<>) },
  40. { typeof(Stack<>), typeof(StackSerializer<>) },
  41. };
  42. }
  43. /// <inheritdoc/>
  44. public override IBsonSerializer GetSerializer(Type type, IBsonSerializerRegistry serializerRegistry)
  45. {
  46. if (type == null)
  47. {
  48. throw new ArgumentNullException("type");
  49. }
  50. var typeInfo = type.GetTypeInfo();
  51. if (typeInfo.IsGenericType && typeInfo.ContainsGenericParameters)
  52. {
  53. var message = string.Format("Generic type {0} has unassigned type parameters.", BsonUtils.GetFriendlyTypeName(type));
  54. throw new ArgumentException(message, "type");
  55. }
  56. Type serializerType;
  57. if (__serializerTypes.TryGetValue(type, out serializerType))
  58. {
  59. return CreateSerializer(serializerType, serializerRegistry);
  60. }
  61. if (typeInfo.IsGenericType && !typeInfo.ContainsGenericParameters)
  62. {
  63. Type serializerTypeDefinition;
  64. if (__serializerTypes.TryGetValue(type.GetGenericTypeDefinition(), out serializerTypeDefinition))
  65. {
  66. return CreateGenericSerializer(serializerTypeDefinition, type.GetTypeInfo().GetGenericArguments(), serializerRegistry);
  67. }
  68. }
  69. if (type.IsArray)
  70. {
  71. var elementType = type.GetElementType();
  72. switch (type.GetArrayRank())
  73. {
  74. case 1:
  75. var arraySerializerDefinition = typeof(ArraySerializer<>);
  76. return CreateGenericSerializer(arraySerializerDefinition, new[] { elementType }, serializerRegistry);
  77. case 2:
  78. var twoDimensionalArraySerializerDefinition = typeof(TwoDimensionalArraySerializer<>);
  79. return CreateGenericSerializer(twoDimensionalArraySerializerDefinition, new[] { elementType }, serializerRegistry);
  80. case 3:
  81. var threeDimensionalArraySerializerDefinition = typeof(ThreeDimensionalArraySerializer<>);
  82. return CreateGenericSerializer(threeDimensionalArraySerializerDefinition, new[] { elementType }, serializerRegistry);
  83. default:
  84. var message = string.Format("No serializer found for array for rank {0}.", type.GetArrayRank());
  85. throw new BsonSerializationException(message);
  86. }
  87. }
  88. return GetCollectionSerializer(type, serializerRegistry);
  89. }
  90. private IBsonSerializer GetCollectionSerializer(Type type, IBsonSerializerRegistry serializerRegistry)
  91. {
  92. Type implementedGenericDictionaryInterface = null;
  93. Type implementedGenericEnumerableInterface = null;
  94. Type implementedGenericSetInterface = null;
  95. Type implementedDictionaryInterface = null;
  96. Type implementedEnumerableInterface = null;
  97. var implementedInterfaces = new List<Type>(type.GetTypeInfo().GetInterfaces());
  98. var typeInfo = type.GetTypeInfo();
  99. if (typeInfo.IsInterface)
  100. {
  101. implementedInterfaces.Add(type);
  102. }
  103. foreach (var implementedInterface in implementedInterfaces)
  104. {
  105. var implementedInterfaceTypeInfo = implementedInterface.GetTypeInfo();
  106. if (implementedInterfaceTypeInfo.IsGenericType)
  107. {
  108. var genericInterfaceDefinition = implementedInterface.GetGenericTypeDefinition();
  109. if (genericInterfaceDefinition == typeof(IDictionary<,>))
  110. {
  111. implementedGenericDictionaryInterface = implementedInterface;
  112. }
  113. if (genericInterfaceDefinition == typeof(IEnumerable<>))
  114. {
  115. implementedGenericEnumerableInterface = implementedInterface;
  116. }
  117. if (genericInterfaceDefinition == typeof(ISet<>))
  118. {
  119. implementedGenericSetInterface = implementedInterface;
  120. }
  121. }
  122. else
  123. {
  124. if (implementedInterface == typeof(IDictionary))
  125. {
  126. implementedDictionaryInterface = implementedInterface;
  127. }
  128. if (implementedInterface == typeof(IEnumerable))
  129. {
  130. implementedEnumerableInterface = implementedInterface;
  131. }
  132. }
  133. }
  134. // the order of the tests is important
  135. if (implementedGenericDictionaryInterface != null)
  136. {
  137. var keyType = implementedGenericDictionaryInterface.GetTypeInfo().GetGenericArguments()[0];
  138. var valueType = implementedGenericDictionaryInterface.GetTypeInfo().GetGenericArguments()[1];
  139. if (typeInfo.IsInterface)
  140. {
  141. var dictionaryDefinition = typeof(Dictionary<,>);
  142. var dictionaryType = dictionaryDefinition.MakeGenericType(keyType, valueType);
  143. var serializerDefinition = typeof(ImpliedImplementationInterfaceSerializer<,>);
  144. return CreateGenericSerializer(serializerDefinition, new[] { type, dictionaryType }, serializerRegistry);
  145. }
  146. else
  147. {
  148. var serializerDefinition = typeof(DictionaryInterfaceImplementerSerializer<,,>);
  149. return CreateGenericSerializer(serializerDefinition, new[] { type, keyType, valueType }, serializerRegistry);
  150. }
  151. }
  152. else if (implementedDictionaryInterface != null)
  153. {
  154. if (typeInfo.IsInterface)
  155. {
  156. var dictionaryType = typeof(Hashtable);
  157. var serializerDefinition = typeof(ImpliedImplementationInterfaceSerializer<,>);
  158. return CreateGenericSerializer(serializerDefinition, new[] { type, dictionaryType }, serializerRegistry);
  159. }
  160. else
  161. {
  162. var serializerDefinition = typeof(DictionaryInterfaceImplementerSerializer<>);
  163. return CreateGenericSerializer(serializerDefinition, new[] { type }, serializerRegistry);
  164. }
  165. }
  166. else if (implementedGenericSetInterface != null)
  167. {
  168. var itemType = implementedGenericSetInterface.GetTypeInfo().GetGenericArguments()[0];
  169. if (typeInfo.IsInterface)
  170. {
  171. var hashSetDefinition = typeof(HashSet<>);
  172. var hashSetType = hashSetDefinition.MakeGenericType(itemType);
  173. var serializerDefinition = typeof(ImpliedImplementationInterfaceSerializer<,>);
  174. return CreateGenericSerializer(serializerDefinition, new[] { type, hashSetType }, serializerRegistry);
  175. }
  176. else
  177. {
  178. var serializerDefinition = typeof(EnumerableInterfaceImplementerSerializer<,>);
  179. return CreateGenericSerializer(serializerDefinition, new[] { type, itemType }, serializerRegistry);
  180. }
  181. }
  182. else if (implementedGenericEnumerableInterface != null)
  183. {
  184. var itemType = implementedGenericEnumerableInterface.GetTypeInfo().GetGenericArguments()[0];
  185. var readOnlyCollectionType = typeof(ReadOnlyCollection<>).MakeGenericType(itemType);
  186. if (type == readOnlyCollectionType)
  187. {
  188. var serializerDefinition = typeof(ReadOnlyCollectionSerializer<>);
  189. return CreateGenericSerializer(serializerDefinition, new[] { itemType }, serializerRegistry);
  190. }
  191. else if (readOnlyCollectionType.GetTypeInfo().IsAssignableFrom(type))
  192. {
  193. var serializerDefinition = typeof(ReadOnlyCollectionSubclassSerializer<,>);
  194. return CreateGenericSerializer(serializerDefinition, new[] { type, itemType }, serializerRegistry);
  195. }
  196. else if (typeInfo.IsInterface)
  197. {
  198. var listDefinition = typeof(List<>);
  199. var listType = listDefinition.MakeGenericType(itemType);
  200. var serializerDefinition = typeof(ImpliedImplementationInterfaceSerializer<,>);
  201. return CreateGenericSerializer(serializerDefinition, new[] { type, listType }, serializerRegistry);
  202. }
  203. else
  204. {
  205. var serializerDefinition = typeof(EnumerableInterfaceImplementerSerializer<,>);
  206. return CreateGenericSerializer(serializerDefinition, new[] { type, itemType }, serializerRegistry);
  207. }
  208. }
  209. else if (implementedEnumerableInterface != null)
  210. {
  211. if (typeInfo.IsInterface)
  212. {
  213. var listType = typeof(ArrayList);
  214. var serializerDefinition = typeof(ImpliedImplementationInterfaceSerializer<,>);
  215. return CreateGenericSerializer(serializerDefinition, new[] { type, listType }, serializerRegistry);
  216. }
  217. else
  218. {
  219. var serializerDefinition = typeof(EnumerableInterfaceImplementerSerializer<>);
  220. return CreateGenericSerializer(serializerDefinition, new[] { type }, serializerRegistry);
  221. }
  222. }
  223. return null;
  224. }
  225. }
  226. }