DictionarySerializerBase.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. /* Copyright 2010-present 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.Expressions;
  19. using MongoDB.Bson.IO;
  20. using MongoDB.Bson.Serialization.Options;
  21. namespace MongoDB.Bson.Serialization.Serializers
  22. {
  23. /// <summary>
  24. /// Represents a serializer for dictionaries.
  25. /// </summary>
  26. /// <typeparam name="TDictionary">The type of the dictionary.</typeparam>
  27. public abstract class DictionarySerializerBase<TDictionary> :
  28. ClassSerializerBase<TDictionary>,
  29. IBsonDocumentSerializer,
  30. IBsonDictionarySerializer
  31. where TDictionary : class, IDictionary
  32. {
  33. // private constants
  34. private static class Flags
  35. {
  36. public const long Key = 1;
  37. public const long Value = 2;
  38. }
  39. // private fields
  40. private readonly DictionaryRepresentation _dictionaryRepresentation;
  41. private readonly SerializerHelper _helper;
  42. private readonly IBsonSerializer _keySerializer;
  43. private readonly IBsonSerializer _valueSerializer;
  44. // constructors
  45. /// <summary>
  46. /// Initializes a new instance of the <see cref="DictionarySerializerBase{TDictionary}"/> class.
  47. /// </summary>
  48. public DictionarySerializerBase()
  49. : this(DictionaryRepresentation.Document)
  50. {
  51. }
  52. /// <summary>
  53. /// Initializes a new instance of the <see cref="DictionarySerializerBase{TDictionary}"/> class.
  54. /// </summary>
  55. /// <param name="dictionaryRepresentation">The dictionary representation.</param>
  56. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation)
  57. : this(dictionaryRepresentation, new ObjectSerializer(), new ObjectSerializer())
  58. {
  59. }
  60. /// <summary>
  61. /// Initializes a new instance of the <see cref="DictionarySerializerBase{TDictionary}"/> class.
  62. /// </summary>
  63. /// <param name="dictionaryRepresentation">The dictionary representation.</param>
  64. /// <param name="keySerializer">The key serializer.</param>
  65. /// <param name="valueSerializer">The value serializer.</param>
  66. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation, IBsonSerializer keySerializer, IBsonSerializer valueSerializer)
  67. {
  68. _dictionaryRepresentation = dictionaryRepresentation;
  69. _keySerializer = keySerializer;
  70. _valueSerializer = valueSerializer;
  71. _helper = new SerializerHelper
  72. (
  73. new SerializerHelper.Member("k", Flags.Key),
  74. new SerializerHelper.Member("v", Flags.Value)
  75. );
  76. }
  77. // public properties
  78. /// <summary>
  79. /// Gets the dictionary representation.
  80. /// </summary>
  81. /// <value>
  82. /// The dictionary representation.
  83. /// </value>
  84. public DictionaryRepresentation DictionaryRepresentation
  85. {
  86. get { return _dictionaryRepresentation; }
  87. }
  88. /// <summary>
  89. /// Gets the key serializer.
  90. /// </summary>
  91. /// <value>
  92. /// The key serializer.
  93. /// </value>
  94. public IBsonSerializer KeySerializer
  95. {
  96. get { return _keySerializer; }
  97. }
  98. /// <summary>
  99. /// Gets the value serializer.
  100. /// </summary>
  101. /// <value>
  102. /// The value serializer.
  103. /// </value>
  104. public IBsonSerializer ValueSerializer
  105. {
  106. get { return _valueSerializer; }
  107. }
  108. // public methods
  109. /// <inheritdoc/>
  110. public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo)
  111. {
  112. if (_dictionaryRepresentation != DictionaryRepresentation.Document)
  113. {
  114. serializationInfo = null;
  115. return false;
  116. }
  117. serializationInfo = new BsonSerializationInfo(
  118. memberName,
  119. _valueSerializer,
  120. _valueSerializer.ValueType);
  121. return true;
  122. }
  123. // protected methods
  124. /// <summary>
  125. /// Deserializes a value.
  126. /// </summary>
  127. /// <param name="context">The deserialization context.</param>
  128. /// <param name="args">The deserialization args.</param>
  129. /// <returns>A deserialized value.</returns>
  130. protected override TDictionary DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args)
  131. {
  132. var bsonReader = context.Reader;
  133. var bsonType = bsonReader.GetCurrentBsonType();
  134. switch (bsonType)
  135. {
  136. case BsonType.Array:
  137. return DeserializeArrayRepresentation(context);
  138. case BsonType.Document:
  139. return DeserializeDocumentRepresentation(context);
  140. default:
  141. throw CreateCannotDeserializeFromBsonTypeException(bsonType);
  142. }
  143. }
  144. /// <summary>
  145. /// Serializes a value.
  146. /// </summary>
  147. /// <param name="context">The serialization context.</param>
  148. /// <param name="args">The serialization args.</param>
  149. /// <param name="value">The object.</param>
  150. protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, TDictionary value)
  151. {
  152. var bsonWriter = context.Writer;
  153. switch (_dictionaryRepresentation)
  154. {
  155. case DictionaryRepresentation.Document:
  156. SerializeDocumentRepresentation(context, value);
  157. break;
  158. case DictionaryRepresentation.ArrayOfArrays:
  159. SerializeArrayOfArraysRepresentation(context, value);
  160. break;
  161. case DictionaryRepresentation.ArrayOfDocuments:
  162. SerializeArrayOfDocumentsRepresentation(context, value);
  163. break;
  164. default:
  165. var message = string.Format("'{0}' is not a valid IDictionary representation.", _dictionaryRepresentation);
  166. throw new BsonSerializationException(message);
  167. }
  168. }
  169. // protected methods
  170. /// <summary>
  171. /// Creates the instance.
  172. /// </summary>
  173. /// <returns>The instance.</returns>
  174. protected abstract TDictionary CreateInstance();
  175. // private methods
  176. private TDictionary DeserializeArrayRepresentation(BsonDeserializationContext context)
  177. {
  178. var dictionary = CreateInstance();
  179. var bsonReader = context.Reader;
  180. bsonReader.ReadStartArray();
  181. while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
  182. {
  183. object key;
  184. object value;
  185. var bsonType = bsonReader.GetCurrentBsonType();
  186. switch (bsonType)
  187. {
  188. case BsonType.Array:
  189. bsonReader.ReadStartArray();
  190. key = _keySerializer.Deserialize(context);
  191. value = _valueSerializer.Deserialize(context);
  192. bsonReader.ReadEndArray();
  193. break;
  194. case BsonType.Document:
  195. key = null;
  196. value = null;
  197. _helper.DeserializeMembers(context, (elementName, flag) =>
  198. {
  199. switch (flag)
  200. {
  201. case Flags.Key: key = _keySerializer.Deserialize(context); break;
  202. case Flags.Value: value = _valueSerializer.Deserialize(context); break;
  203. }
  204. });
  205. break;
  206. default:
  207. throw CreateCannotDeserializeFromBsonTypeException(bsonType);
  208. }
  209. dictionary.Add(key, value);
  210. }
  211. bsonReader.ReadEndArray();
  212. return dictionary;
  213. }
  214. private TDictionary DeserializeDocumentRepresentation(BsonDeserializationContext context)
  215. {
  216. var dictionary = CreateInstance();
  217. var bsonReader = context.Reader;
  218. bsonReader.ReadStartDocument();
  219. while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
  220. {
  221. var key = DeserializeKeyString(bsonReader.ReadName());
  222. var value = _valueSerializer.Deserialize(context);
  223. dictionary.Add(key, value);
  224. }
  225. bsonReader.ReadEndDocument();
  226. return dictionary;
  227. }
  228. private object DeserializeKeyString(string keyString)
  229. {
  230. var keyDocument = new BsonDocument("k", keyString);
  231. using (var keyReader = new BsonDocumentReader(keyDocument))
  232. {
  233. var context = BsonDeserializationContext.CreateRoot(keyReader);
  234. keyReader.ReadStartDocument();
  235. keyReader.ReadName("k");
  236. var key = _keySerializer.Deserialize(context);
  237. keyReader.ReadEndDocument();
  238. return key;
  239. }
  240. }
  241. private void SerializeArrayOfArraysRepresentation(BsonSerializationContext context, TDictionary value)
  242. {
  243. var bsonWriter = context.Writer;
  244. bsonWriter.WriteStartArray();
  245. foreach (DictionaryEntry dictionaryEntry in value)
  246. {
  247. bsonWriter.WriteStartArray();
  248. _keySerializer.Serialize(context, dictionaryEntry.Key);
  249. _valueSerializer.Serialize(context, dictionaryEntry.Value);
  250. bsonWriter.WriteEndArray();
  251. }
  252. bsonWriter.WriteEndArray();
  253. }
  254. private void SerializeArrayOfDocumentsRepresentation(BsonSerializationContext context, TDictionary value)
  255. {
  256. var bsonWriter = context.Writer;
  257. bsonWriter.WriteStartArray();
  258. foreach (DictionaryEntry dictionaryEntry in value)
  259. {
  260. bsonWriter.WriteStartDocument();
  261. bsonWriter.WriteName("k");
  262. _keySerializer.Serialize(context, dictionaryEntry.Key);
  263. bsonWriter.WriteName("v");
  264. _valueSerializer.Serialize(context, dictionaryEntry.Value);
  265. bsonWriter.WriteEndDocument();
  266. }
  267. bsonWriter.WriteEndArray();
  268. }
  269. private void SerializeDocumentRepresentation(BsonSerializationContext context, TDictionary value)
  270. {
  271. var bsonWriter = context.Writer;
  272. bsonWriter.WriteStartDocument();
  273. foreach (DictionaryEntry dictionaryEntry in value)
  274. {
  275. bsonWriter.WriteName(SerializeKeyString(dictionaryEntry.Key));
  276. _valueSerializer.Serialize(context, dictionaryEntry.Value);
  277. }
  278. bsonWriter.WriteEndDocument();
  279. }
  280. private string SerializeKeyString(object key)
  281. {
  282. var keyDocument = new BsonDocument();
  283. using (var keyWriter = new BsonDocumentWriter(keyDocument))
  284. {
  285. var context = BsonSerializationContext.CreateRoot(keyWriter);
  286. keyWriter.WriteStartDocument();
  287. keyWriter.WriteName("k");
  288. _keySerializer.Serialize(context, key);
  289. keyWriter.WriteEndDocument();
  290. }
  291. var keyValue = keyDocument["k"];
  292. if (keyValue.BsonType != BsonType.String)
  293. {
  294. throw new BsonSerializationException("When using DictionaryRepresentation.Document key values must serialize as strings.");
  295. }
  296. return (string)keyValue;
  297. }
  298. }
  299. /// <summary>
  300. /// Represents a serializer for dictionaries.
  301. /// </summary>
  302. /// <typeparam name="TDictionary">The type of the dictionary.</typeparam>
  303. /// <typeparam name="TKey">The type of the keys.</typeparam>
  304. /// <typeparam name="TValue">The type of the values.</typeparam>
  305. public abstract class DictionarySerializerBase<TDictionary, TKey, TValue> :
  306. ClassSerializerBase<TDictionary>,
  307. IBsonArraySerializer,
  308. IBsonDocumentSerializer,
  309. IBsonDictionarySerializer
  310. where TDictionary : class, IEnumerable<KeyValuePair<TKey, TValue>>
  311. {
  312. // private constants
  313. private static class Flags
  314. {
  315. public const long Key = 1;
  316. public const long Value = 2;
  317. }
  318. // private fields
  319. private readonly DictionaryRepresentation _dictionaryRepresentation;
  320. private readonly SerializerHelper _helper;
  321. private readonly Lazy<IBsonSerializer<TKey>> _lazyKeySerializer;
  322. private readonly Lazy<IBsonSerializer<TValue>> _lazyValueSerializer;
  323. // constructors
  324. /// <summary>
  325. /// Initializes a new instance of the <see cref="DictionarySerializerBase{TDictionary, TKey, TValue}"/> class.
  326. /// </summary>
  327. public DictionarySerializerBase()
  328. : this(DictionaryRepresentation.Document)
  329. {
  330. }
  331. /// <summary>
  332. /// Initializes a new instance of the <see cref="DictionarySerializerBase{TDictionary, TKey, TValue}" /> class.
  333. /// </summary>
  334. /// <param name="dictionaryRepresentation">The dictionary representation.</param>
  335. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation)
  336. : this(dictionaryRepresentation, BsonSerializer.SerializerRegistry)
  337. {
  338. }
  339. /// <summary>
  340. /// Initializes a new instance of the <see cref="DictionarySerializerBase{TDictionary, TKey, TValue}" /> class.
  341. /// </summary>
  342. /// <param name="dictionaryRepresentation">The dictionary representation.</param>
  343. /// <param name="keySerializer">The key serializer.</param>
  344. /// <param name="valueSerializer">The value serializer.</param>
  345. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation, IBsonSerializer<TKey> keySerializer, IBsonSerializer<TValue> valueSerializer)
  346. : this(
  347. dictionaryRepresentation,
  348. new Lazy<IBsonSerializer<TKey>>(() => keySerializer),
  349. new Lazy<IBsonSerializer<TValue>>(() => valueSerializer))
  350. {
  351. if (keySerializer == null)
  352. {
  353. throw new ArgumentNullException("keySerializer");
  354. }
  355. if (valueSerializer == null)
  356. {
  357. throw new ArgumentNullException("valueSerializer");
  358. }
  359. }
  360. /// <summary>
  361. /// Initializes a new instance of the <see cref="DictionarySerializerBase{TDictionary, TKey, TValue}" /> class.
  362. /// </summary>
  363. /// <param name="dictionaryRepresentation">The dictionary representation.</param>
  364. /// <param name="serializerRegistry">The serializer registry.</param>
  365. public DictionarySerializerBase(DictionaryRepresentation dictionaryRepresentation, IBsonSerializerRegistry serializerRegistry)
  366. : this(
  367. dictionaryRepresentation,
  368. new Lazy<IBsonSerializer<TKey>>(() => serializerRegistry.GetSerializer<TKey>()),
  369. new Lazy<IBsonSerializer<TValue>>(() => serializerRegistry.GetSerializer<TValue>()))
  370. {
  371. if (serializerRegistry == null)
  372. {
  373. throw new ArgumentNullException("serializerRegistry");
  374. }
  375. }
  376. private DictionarySerializerBase(
  377. DictionaryRepresentation dictionaryRepresentation,
  378. Lazy<IBsonSerializer<TKey>> lazyKeySerializer,
  379. Lazy<IBsonSerializer<TValue>> lazyValueSerializer)
  380. {
  381. _dictionaryRepresentation = dictionaryRepresentation;
  382. _lazyKeySerializer = lazyKeySerializer;
  383. _lazyValueSerializer = lazyValueSerializer;
  384. _helper = new SerializerHelper
  385. (
  386. new SerializerHelper.Member("k", Flags.Key),
  387. new SerializerHelper.Member("v", Flags.Value)
  388. );
  389. }
  390. // public properties
  391. /// <summary>
  392. /// Gets the dictionary representation.
  393. /// </summary>
  394. /// <value>
  395. /// The dictionary representation.
  396. /// </value>
  397. public DictionaryRepresentation DictionaryRepresentation
  398. {
  399. get { return _dictionaryRepresentation; }
  400. }
  401. /// <summary>
  402. /// Gets the key serializer.
  403. /// </summary>
  404. /// <value>
  405. /// The key serializer.
  406. /// </value>
  407. public IBsonSerializer<TKey> KeySerializer
  408. {
  409. get { return _lazyKeySerializer.Value; }
  410. }
  411. /// <summary>
  412. /// Gets the value serializer.
  413. /// </summary>
  414. /// <value>
  415. /// The value serializer.
  416. /// </value>
  417. public IBsonSerializer<TValue> ValueSerializer
  418. {
  419. get { return _lazyValueSerializer.Value; }
  420. }
  421. // public methods
  422. /// <inheritdoc/>
  423. public bool TryGetItemSerializationInfo(out BsonSerializationInfo serializationInfo)
  424. {
  425. if (_dictionaryRepresentation != DictionaryRepresentation.ArrayOfDocuments)
  426. {
  427. serializationInfo = null;
  428. return false;
  429. }
  430. var serializer = new KeyValuePairSerializer<TKey, TValue>(
  431. BsonType.Document,
  432. _lazyKeySerializer.Value,
  433. _lazyValueSerializer.Value);
  434. serializationInfo = new BsonSerializationInfo(
  435. null,
  436. serializer,
  437. serializer.ValueType);
  438. return true;
  439. }
  440. /// <inheritdoc/>
  441. public bool TryGetMemberSerializationInfo(string memberName, out BsonSerializationInfo serializationInfo)
  442. {
  443. if (_dictionaryRepresentation != DictionaryRepresentation.Document)
  444. {
  445. serializationInfo = null;
  446. return false;
  447. }
  448. serializationInfo = new BsonSerializationInfo(
  449. memberName,
  450. _lazyValueSerializer.Value,
  451. _lazyValueSerializer.Value.ValueType);
  452. return true;
  453. }
  454. // protected methods
  455. /// <summary>
  456. /// Deserializes a value.
  457. /// </summary>
  458. /// <param name="context">The deserialization context.</param>
  459. /// <param name="args">The deserialization args.</param>
  460. /// <returns>A deserialized value.</returns>
  461. protected override TDictionary DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args)
  462. {
  463. var bsonReader = context.Reader;
  464. var bsonType = bsonReader.GetCurrentBsonType();
  465. switch (bsonType)
  466. {
  467. case BsonType.Array:
  468. return DeserializeArrayRepresentation(context);
  469. case BsonType.Document:
  470. return DeserializeDocumentRepresentation(context);
  471. default:
  472. throw CreateCannotDeserializeFromBsonTypeException(bsonType);
  473. }
  474. }
  475. /// <summary>
  476. /// Serializes a value.
  477. /// </summary>
  478. /// <param name="context">The serialization context.</param>
  479. /// <param name="args">The serialization args.</param>
  480. /// <param name="value">The object.</param>
  481. protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, TDictionary value)
  482. {
  483. var bsonWriter = context.Writer;
  484. switch (_dictionaryRepresentation)
  485. {
  486. case DictionaryRepresentation.Document:
  487. SerializeDocumentRepresentation(context, value);
  488. break;
  489. case DictionaryRepresentation.ArrayOfArrays:
  490. SerializeArrayOfArraysRepresentation(context, value);
  491. break;
  492. case DictionaryRepresentation.ArrayOfDocuments:
  493. SerializeArrayOfDocumentsRepresentation(context, value);
  494. break;
  495. default:
  496. var message = string.Format("'{0}' is not a valid IDictionary<{1}, {2}> representation.",
  497. _dictionaryRepresentation,
  498. BsonUtils.GetFriendlyTypeName(typeof(TKey)),
  499. BsonUtils.GetFriendlyTypeName(typeof(TValue)));
  500. throw new BsonSerializationException(message);
  501. }
  502. }
  503. // protected methods
  504. /// <summary>
  505. /// Creates an accumulator.
  506. /// </summary>
  507. /// <returns>The accumulator.</returns>
  508. protected virtual ICollection<KeyValuePair<TKey, TValue>> CreateAccumulator()
  509. {
  510. #pragma warning disable 618
  511. return (ICollection<KeyValuePair<TKey, TValue>>)CreateInstance();
  512. #pragma warning restore 618
  513. }
  514. // protected methods
  515. /// <summary>
  516. /// Creates the instance.
  517. /// </summary>
  518. /// <returns>The instance.</returns>
  519. [Obsolete("CreateInstance is deprecated. Please use CreateAccumulator instead.")]
  520. protected virtual TDictionary CreateInstance()
  521. {
  522. throw new NotImplementedException();
  523. }
  524. /// <summary>
  525. /// Finalizes an accumulator.
  526. /// </summary>
  527. /// <param name="accumulator">The accumulator to finalize</param>
  528. /// <returns>The instance.</returns>
  529. protected virtual TDictionary FinalizeAccumulator(ICollection<KeyValuePair<TKey, TValue>> accumulator)
  530. {
  531. return (TDictionary)accumulator;
  532. }
  533. // private methods
  534. private TDictionary DeserializeArrayRepresentation(BsonDeserializationContext context)
  535. {
  536. var accumulator = CreateAccumulator();
  537. var bsonReader = context.Reader;
  538. bsonReader.ReadStartArray();
  539. while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
  540. {
  541. TKey key;
  542. TValue value;
  543. var bsonType = bsonReader.GetCurrentBsonType();
  544. switch (bsonType)
  545. {
  546. case BsonType.Array:
  547. bsonReader.ReadStartArray();
  548. key = _lazyKeySerializer.Value.Deserialize(context);
  549. value = _lazyValueSerializer.Value.Deserialize(context);
  550. bsonReader.ReadEndArray();
  551. break;
  552. case BsonType.Document:
  553. key = default(TKey);
  554. value = default(TValue);
  555. _helper.DeserializeMembers(context, (elementName, flag) =>
  556. {
  557. switch (flag)
  558. {
  559. case Flags.Key: key = _lazyKeySerializer.Value.Deserialize(context); break;
  560. case Flags.Value: value = _lazyValueSerializer.Value.Deserialize(context); break;
  561. }
  562. });
  563. break;
  564. default:
  565. throw CreateCannotDeserializeFromBsonTypeException(bsonType);
  566. }
  567. accumulator.Add(new KeyValuePair<TKey, TValue>(key, value));
  568. }
  569. bsonReader.ReadEndArray();
  570. return FinalizeAccumulator(accumulator);
  571. }
  572. private TDictionary DeserializeDocumentRepresentation(BsonDeserializationContext context)
  573. {
  574. var accumulator = CreateAccumulator();
  575. var bsonReader = context.Reader;
  576. bsonReader.ReadStartDocument();
  577. while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
  578. {
  579. var key = DeserializeKeyString(bsonReader.ReadName());
  580. var value = _lazyValueSerializer.Value.Deserialize(context);
  581. accumulator.Add(new KeyValuePair<TKey, TValue>(key, value));
  582. }
  583. bsonReader.ReadEndDocument();
  584. return FinalizeAccumulator(accumulator);
  585. }
  586. private TKey DeserializeKeyString(string keyString)
  587. {
  588. var keyDocument = new BsonDocument("k", keyString);
  589. using (var keyReader = new BsonDocumentReader(keyDocument))
  590. {
  591. var context = BsonDeserializationContext.CreateRoot(keyReader);
  592. keyReader.ReadStartDocument();
  593. keyReader.ReadName("k");
  594. var key = _lazyKeySerializer.Value.Deserialize(context);
  595. keyReader.ReadEndDocument();
  596. return key;
  597. }
  598. }
  599. private void SerializeArrayOfArraysRepresentation(BsonSerializationContext context, TDictionary value)
  600. {
  601. var bsonWriter = context.Writer;
  602. bsonWriter.WriteStartArray();
  603. foreach (var keyValuePair in value)
  604. {
  605. bsonWriter.WriteStartArray();
  606. _lazyKeySerializer.Value.Serialize(context, keyValuePair.Key);
  607. _lazyValueSerializer.Value.Serialize(context, keyValuePair.Value);
  608. bsonWriter.WriteEndArray();
  609. }
  610. bsonWriter.WriteEndArray();
  611. }
  612. private void SerializeArrayOfDocumentsRepresentation(BsonSerializationContext context, TDictionary value)
  613. {
  614. var bsonWriter = context.Writer;
  615. bsonWriter.WriteStartArray();
  616. foreach (var keyValuePair in value)
  617. {
  618. bsonWriter.WriteStartDocument();
  619. bsonWriter.WriteName("k");
  620. _lazyKeySerializer.Value.Serialize(context, keyValuePair.Key);
  621. bsonWriter.WriteName("v");
  622. _lazyValueSerializer.Value.Serialize(context, keyValuePair.Value);
  623. bsonWriter.WriteEndDocument();
  624. }
  625. bsonWriter.WriteEndArray();
  626. }
  627. private void SerializeDocumentRepresentation(BsonSerializationContext context, TDictionary value)
  628. {
  629. var bsonWriter = context.Writer;
  630. bsonWriter.WriteStartDocument();
  631. foreach (var keyValuePair in value)
  632. {
  633. bsonWriter.WriteName(SerializeKeyString(keyValuePair.Key));
  634. _lazyValueSerializer.Value.Serialize(context, keyValuePair.Value);
  635. }
  636. bsonWriter.WriteEndDocument();
  637. }
  638. private string SerializeKeyString(TKey key)
  639. {
  640. var keyDocument = new BsonDocument();
  641. using (var keyWriter = new BsonDocumentWriter(keyDocument))
  642. {
  643. var context = BsonSerializationContext.CreateRoot(keyWriter);
  644. keyWriter.WriteStartDocument();
  645. keyWriter.WriteName("k");
  646. _lazyKeySerializer.Value.Serialize(context, key);
  647. keyWriter.WriteEndDocument();
  648. }
  649. var keyValue = keyDocument["k"];
  650. if (keyValue.BsonType != BsonType.String)
  651. {
  652. throw new BsonSerializationException("When using DictionaryRepresentation.Document key values must serialize as strings.");
  653. }
  654. return (string)keyValue;
  655. }
  656. // explicit interface implementations
  657. IBsonSerializer IBsonDictionarySerializer.KeySerializer
  658. {
  659. get { return KeySerializer; }
  660. }
  661. IBsonSerializer IBsonDictionarySerializer.ValueSerializer
  662. {
  663. get { return ValueSerializer; }
  664. }
  665. }
  666. }