TwoDimensionalArraySerializer.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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.Generic;
  17. namespace MongoDB.Bson.Serialization.Serializers
  18. {
  19. /// <summary>
  20. /// Represents a serializer for two-dimensional arrays.
  21. /// </summary>
  22. /// <typeparam name="TItem">The type of the elements.</typeparam>
  23. public class TwoDimensionalArraySerializer<TItem> :
  24. SealedClassSerializerBase<TItem[,]>,
  25. IChildSerializerConfigurable
  26. {
  27. // private fields
  28. private readonly Lazy<IBsonSerializer<TItem>> _lazyItemSerializer;
  29. // constructors
  30. /// <summary>
  31. /// Initializes a new instance of the <see cref="TwoDimensionalArraySerializer{TItem}"/> class.
  32. /// </summary>
  33. public TwoDimensionalArraySerializer()
  34. : this(BsonSerializer.SerializerRegistry)
  35. {
  36. }
  37. /// <summary>
  38. /// Initializes a new instance of the <see cref="TwoDimensionalArraySerializer{TItem}"/> class.
  39. /// </summary>
  40. /// <param name="itemSerializer">The item serializer.</param>
  41. public TwoDimensionalArraySerializer(IBsonSerializer<TItem> itemSerializer)
  42. {
  43. if (itemSerializer == null)
  44. {
  45. throw new ArgumentNullException("itemSerializer");
  46. }
  47. _lazyItemSerializer = new Lazy<IBsonSerializer<TItem>>(() => itemSerializer);
  48. }
  49. /// <summary>
  50. /// Initializes a new instance of the <see cref="TwoDimensionalArraySerializer{TItem}" /> class.
  51. /// </summary>
  52. /// <param name="serializerRegistry">The serializer registry.</param>
  53. public TwoDimensionalArraySerializer(IBsonSerializerRegistry serializerRegistry)
  54. {
  55. if (serializerRegistry == null)
  56. {
  57. throw new ArgumentNullException("serializerRegistry");
  58. }
  59. _lazyItemSerializer = new Lazy<IBsonSerializer<TItem>>(() => serializerRegistry.GetSerializer<TItem>());
  60. }
  61. // public properties
  62. /// <summary>
  63. /// Gets the item serializer.
  64. /// </summary>
  65. /// <value>
  66. /// The item serializer.
  67. /// </value>
  68. public IBsonSerializer<TItem> ItemSerializer
  69. {
  70. get { return _lazyItemSerializer.Value; }
  71. }
  72. // public methods
  73. /// <summary>
  74. /// Deserializes a value.
  75. /// </summary>
  76. /// <param name="context">The deserialization context.</param>
  77. /// <param name="args">The deserialization args.</param>
  78. /// <returns>A deserialized value.</returns>
  79. protected override TItem[,] DeserializeValue(BsonDeserializationContext context, BsonDeserializationArgs args)
  80. {
  81. var bsonReader = context.Reader;
  82. EnsureBsonTypeEquals(bsonReader, BsonType.Array);
  83. bsonReader.ReadStartArray();
  84. var outerList = new List<List<TItem>>();
  85. while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
  86. {
  87. bsonReader.ReadStartArray();
  88. var innerList = new List<TItem>();
  89. while (bsonReader.ReadBsonType() != BsonType.EndOfDocument)
  90. {
  91. innerList.Add(_lazyItemSerializer.Value.Deserialize(context));
  92. }
  93. bsonReader.ReadEndArray();
  94. outerList.Add(innerList);
  95. }
  96. bsonReader.ReadEndArray();
  97. var length1 = outerList.Count;
  98. var length2 = (length1 == 0) ? 0 : outerList[0].Count;
  99. var array = new TItem[length1, length2];
  100. for (int i = 0; i < length1; i++)
  101. {
  102. var innerList = outerList[i];
  103. if (innerList.Count != length2)
  104. {
  105. var message = string.Format("Inner list {0} is of length {1} but should be of length {2}.", i, innerList.Count, length2);
  106. throw new FormatException(message);
  107. }
  108. for (int j = 0; j < length2; j++)
  109. {
  110. array[i, j] = innerList[j];
  111. }
  112. }
  113. return array;
  114. }
  115. /// <summary>
  116. /// Serializes a value.
  117. /// </summary>
  118. /// <param name="context">The serialization context.</param>
  119. /// <param name="args">The serialization args.</param>
  120. /// <param name="value">The object.</param>
  121. protected override void SerializeValue(BsonSerializationContext context, BsonSerializationArgs args, TItem[,] value)
  122. {
  123. var bsonWriter = context.Writer;
  124. var length1 = value.GetLength(0);
  125. var length2 = value.GetLength(1);
  126. bsonWriter.WriteStartArray();
  127. for (int i = 0; i < length1; i++)
  128. {
  129. bsonWriter.WriteStartArray();
  130. for (int j = 0; j < length2; j++)
  131. {
  132. _lazyItemSerializer.Value.Serialize(context, value[i, j]);
  133. }
  134. bsonWriter.WriteEndArray();
  135. }
  136. bsonWriter.WriteEndArray();
  137. }
  138. /// <summary>
  139. /// Returns a serializer that has been reconfigured with the specified item serializer.
  140. /// </summary>
  141. /// <param name="itemSerializer">The item serializer.</param>
  142. /// <returns>The reconfigured serializer.</returns>
  143. public TwoDimensionalArraySerializer<TItem> WithItemSerializer(IBsonSerializer<TItem> itemSerializer)
  144. {
  145. return new TwoDimensionalArraySerializer<TItem>(itemSerializer);
  146. }
  147. // explicit interface implementations
  148. IBsonSerializer IChildSerializerConfigurable.ChildSerializer
  149. {
  150. get { return ItemSerializer; }
  151. }
  152. IBsonSerializer IChildSerializerConfigurable.WithChildSerializer(IBsonSerializer childSerializer)
  153. {
  154. return WithItemSerializer((IBsonSerializer<TItem>)childSerializer);
  155. }
  156. }
  157. }