BsonDocumentWrapper.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  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.Linq;
  19. using MongoDB.Bson.IO;
  20. using MongoDB.Bson.Serialization;
  21. using MongoDB.Bson.Serialization.Serializers;
  22. namespace MongoDB.Bson
  23. {
  24. // this class is a wrapper for an object that we intend to serialize as a BsonDocument
  25. // it is a subclass of BsonDocument so that it may be used where a BsonDocument is expected
  26. // this class is mostly used by MongoCollection and MongoCursor when supporting generic query objects
  27. // if all that ever happens with this wrapped object is that it gets serialized then the BsonDocument is never materialized
  28. /// <summary>
  29. /// Represents a BsonDocument wrapper.
  30. /// </summary>
  31. public class BsonDocumentWrapper : MaterializedOnDemandBsonDocument
  32. {
  33. // private fields
  34. private Type _wrappedNominalType;
  35. private object _wrappedObject;
  36. private IBsonSerializer _serializer;
  37. private IBsonSerializationOptions _serializationOptions;
  38. private bool _isUpdateDocument;
  39. // constructors
  40. // needed for Deserialize
  41. // (even though we're going to end up throwing an InvalidOperationException)
  42. private BsonDocumentWrapper()
  43. {
  44. }
  45. /// <summary>
  46. /// Initializes a new instance of the BsonDocumentWrapper class.
  47. /// </summary>
  48. /// <param name="wrappedObject">The wrapped object.</param>
  49. public BsonDocumentWrapper(object wrappedObject)
  50. : this((wrappedObject == null) ? typeof(object) : wrappedObject.GetType(), wrappedObject)
  51. {
  52. }
  53. /// <summary>
  54. /// Initializes a new instance of the BsonDocumentWrapper class.
  55. /// </summary>
  56. /// <param name="wrappedNominalType">The nominal type of the wrapped object.</param>
  57. /// <param name="wrappedObject">The wrapped object.</param>
  58. public BsonDocumentWrapper(Type wrappedNominalType, object wrappedObject)
  59. : this(wrappedNominalType, wrappedObject, false)
  60. {
  61. }
  62. /// <summary>
  63. /// Initializes a new instance of the BsonDocumentWrapper class.
  64. /// </summary>
  65. /// <param name="wrappedNominalType">The nominal type of the wrapped object.</param>
  66. /// <param name="wrappedObject">The wrapped object.</param>
  67. /// <param name="isUpdateDocument">Whether the wrapped object is an update document that needs to be checked.</param>
  68. public BsonDocumentWrapper(Type wrappedNominalType, object wrappedObject, bool isUpdateDocument)
  69. : this(wrappedNominalType, wrappedObject, BsonSerializer.LookupSerializer(wrappedNominalType), null, isUpdateDocument)
  70. {
  71. }
  72. /// <summary>
  73. /// Initializes a new instance of the BsonDocumentWrapper class.
  74. /// </summary>
  75. /// <param name="wrappedNominalType">The nominal type of the wrapped object.</param>
  76. /// <param name="wrappedObject">The wrapped object.</param>
  77. /// <param name="serializer">The serializer.</param>
  78. /// <param name="serializationOptions">The serialization options.</param>
  79. /// <param name="isUpdateDocument">Whether the wrapped object is an update document that needs to be checked.</param>
  80. public BsonDocumentWrapper(Type wrappedNominalType, object wrappedObject, IBsonSerializer serializer, IBsonSerializationOptions serializationOptions, bool isUpdateDocument)
  81. {
  82. if (wrappedNominalType == null)
  83. {
  84. throw new ArgumentNullException("wrappedNominalType");
  85. }
  86. if (serializer == null)
  87. {
  88. throw new ArgumentNullException("serializer");
  89. }
  90. _wrappedNominalType = wrappedNominalType;
  91. _wrappedObject = wrappedObject;
  92. _serializer = serializer;
  93. _serializationOptions = serializationOptions;
  94. _isUpdateDocument = isUpdateDocument;
  95. }
  96. // public properties
  97. /// <summary>
  98. /// Gets whether the wrapped document is an update document.
  99. /// </summary>
  100. public bool IsUpdateDocument
  101. {
  102. get { return _isUpdateDocument; }
  103. }
  104. /// <summary>
  105. /// Gets the serialization options.
  106. /// </summary>
  107. /// <value>
  108. /// The serialization options.
  109. /// </value>
  110. public IBsonSerializationOptions SerializationOptions
  111. {
  112. get { return _serializationOptions; }
  113. }
  114. /// <summary>
  115. /// Gets the serializer.
  116. /// </summary>
  117. /// <value>
  118. /// The serializer.
  119. /// </value>
  120. public IBsonSerializer Serializer
  121. {
  122. get { return _serializer; }
  123. }
  124. /// <summary>
  125. /// Gets the nominal type of the wrapped document.
  126. /// </summary>
  127. public Type WrappedNominalType
  128. {
  129. get { return _wrappedNominalType; }
  130. }
  131. /// <summary>
  132. /// Gets the wrapped object.
  133. /// </summary>
  134. public object WrappedObject
  135. {
  136. get { return _wrappedObject; }
  137. }
  138. // public static methods
  139. /// <summary>
  140. /// Creates a new instance of the BsonDocumentWrapper class.
  141. /// </summary>
  142. /// <typeparam name="TNominalType">The nominal type of the wrapped object.</typeparam>
  143. /// <param name="value">The wrapped object.</param>
  144. /// <returns>A BsonDocumentWrapper.</returns>
  145. public static BsonDocumentWrapper Create<TNominalType>(TNominalType value)
  146. {
  147. return Create(typeof(TNominalType), value);
  148. }
  149. /// <summary>
  150. /// Creates a new instance of the BsonDocumentWrapper class.
  151. /// </summary>
  152. /// <typeparam name="TNominalType">The nominal type of the wrapped object.</typeparam>
  153. /// <param name="value">The wrapped object.</param>
  154. /// <param name="isUpdateDocument">Whether the wrapped object is an update document.</param>
  155. /// <returns>A BsonDocumentWrapper.</returns>
  156. public static BsonDocumentWrapper Create<TNominalType>(TNominalType value, bool isUpdateDocument)
  157. {
  158. return Create(typeof(TNominalType), value, isUpdateDocument);
  159. }
  160. /// <summary>
  161. /// Creates a new instance of the BsonDocumentWrapper class.
  162. /// </summary>
  163. /// <param name="nominalType">The nominal type of the wrapped object.</param>
  164. /// <param name="value">The wrapped object.</param>
  165. /// <returns>A BsonDocumentWrapper.</returns>
  166. public static BsonDocumentWrapper Create(Type nominalType, object value)
  167. {
  168. return Create(nominalType, value, false); // isUpdateDocument = false
  169. }
  170. /// <summary>
  171. /// Creates a new instance of the BsonDocumentWrapper class.
  172. /// </summary>
  173. /// <param name="nominalType">The nominal type of the wrapped object.</param>
  174. /// <param name="value">The wrapped object.</param>
  175. /// <param name="isUpdateDocument">Whether the wrapped object is an update document.</param>
  176. /// <returns>A BsonDocumentWrapper.</returns>
  177. public static BsonDocumentWrapper Create(Type nominalType, object value, bool isUpdateDocument)
  178. {
  179. return new BsonDocumentWrapper(nominalType, value, isUpdateDocument);
  180. }
  181. /// <summary>
  182. /// Creates a list of new instances of the BsonDocumentWrapper class.
  183. /// </summary>
  184. /// <typeparam name="TNominalType">The nominal type of the wrapped objects.</typeparam>
  185. /// <param name="values">A list of wrapped objects.</param>
  186. /// <returns>A list of BsonDocumentWrappers.</returns>
  187. public static IEnumerable<BsonDocumentWrapper> CreateMultiple<TNominalType>(IEnumerable<TNominalType> values)
  188. {
  189. if (values == null)
  190. {
  191. throw new ArgumentNullException("values");
  192. }
  193. return values.Select(v => new BsonDocumentWrapper(typeof(TNominalType), v));
  194. }
  195. /// <summary>
  196. /// Creates a list of new instances of the BsonDocumentWrapper class.
  197. /// </summary>
  198. /// <param name="nominalType">The nominal type of the wrapped object.</param>
  199. /// <param name="values">A list of wrapped objects.</param>
  200. /// <returns>A list of BsonDocumentWrappers.</returns>
  201. public static IEnumerable<BsonDocumentWrapper> CreateMultiple(Type nominalType, IEnumerable values)
  202. {
  203. if (nominalType == null)
  204. {
  205. throw new ArgumentNullException("nominalType");
  206. }
  207. if (values == null)
  208. {
  209. throw new ArgumentNullException("values");
  210. }
  211. return values.Cast<object>().Select(v => new BsonDocumentWrapper(nominalType, v));
  212. }
  213. // public methods
  214. /// <summary>
  215. /// Creates a shallow clone of the document (see also DeepClone).
  216. /// </summary>
  217. /// <returns>
  218. /// A shallow clone of the document.
  219. /// </returns>
  220. public override BsonValue Clone()
  221. {
  222. if (IsMaterialized)
  223. {
  224. return base.Clone();
  225. }
  226. else
  227. {
  228. return new BsonDocumentWrapper(
  229. _wrappedNominalType,
  230. _wrappedObject,
  231. _serializer,
  232. _serializationOptions,
  233. _isUpdateDocument);
  234. }
  235. }
  236. /// <summary>
  237. /// Deserialize is an invalid operation for BsonDocumentWrapper.
  238. /// </summary>
  239. /// <param name="bsonReader">Not applicable.</param>
  240. /// <param name="nominalType">Not applicable.</param>
  241. /// <param name="options">Not applicable.</param>
  242. /// <returns>Not applicable.</returns>
  243. [Obsolete("Deserialize was intended to be private and will become private in a future release.")]
  244. public override object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
  245. {
  246. throw new NotSupportedException();
  247. }
  248. /// <summary>
  249. /// Serializes the wrapped object to a BsonWriter.
  250. /// </summary>
  251. /// <param name="bsonWriter">The writer.</param>
  252. /// <param name="nominalType">The nominal type (overridden by the wrapped nominal type).</param>
  253. /// <param name="options">The serialization options (can be null).</param>
  254. [Obsolete("Serialize was intended to be private and will become private in a future release.")]
  255. public override void Serialize(BsonWriter bsonWriter, Type nominalType, IBsonSerializationOptions options)
  256. {
  257. BsonDocumentWrapperSerializer.Instance.Serialize(bsonWriter, nominalType, this, options);
  258. }
  259. // protected methods
  260. /// <summary>
  261. /// Materializes the BsonDocument.
  262. /// </summary>
  263. /// <returns>The materialized elements.</returns>
  264. protected override IEnumerable<BsonElement> Materialize()
  265. {
  266. var bsonDocument = new BsonDocument();
  267. var writerSettings = BsonDocumentWriterSettings.Defaults;
  268. using (var bsonWriter = new BsonDocumentWriter(bsonDocument, writerSettings))
  269. {
  270. BsonDocumentWrapperSerializer.Instance.Serialize(bsonWriter, typeof(BsonDocumentWrapper), this, null);
  271. }
  272. return bsonDocument.Elements;
  273. }
  274. /// <summary>
  275. /// Informs subclasses that the Materialize process completed so they can free any resources related to the unmaterialized state.
  276. /// </summary>
  277. protected override void MaterializeCompleted()
  278. {
  279. }
  280. }
  281. }