DictionarySerializerBase.cs 27 KB

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