DecimalSerializer.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /* Copyright 2016-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 MongoDB.Bson.IO;
  17. using MongoDB.Bson.Serialization.Options;
  18. namespace MongoDB.Bson.Serialization.Serializers
  19. {
  20. /// <summary>
  21. /// Represents a serializer for Decimals.
  22. /// </summary>
  23. public class DecimalSerializer : StructSerializerBase<decimal>, IRepresentationConfigurable<DecimalSerializer>, IRepresentationConverterConfigurable<DecimalSerializer>
  24. {
  25. // private fields
  26. private readonly BsonType _representation;
  27. private readonly RepresentationConverter _converter;
  28. // constructors
  29. /// <summary>
  30. /// Initializes a new instance of the <see cref="DecimalSerializer"/> class.
  31. /// </summary>
  32. public DecimalSerializer()
  33. : this(BsonType.String)
  34. {
  35. }
  36. /// <summary>
  37. /// Initializes a new instance of the <see cref="DecimalSerializer"/> class.
  38. /// </summary>
  39. /// <param name="representation">The representation.</param>
  40. public DecimalSerializer(BsonType representation)
  41. : this(representation, new RepresentationConverter(false, false))
  42. {
  43. }
  44. /// <summary>
  45. /// Initializes a new instance of the <see cref="DecimalSerializer"/> class.
  46. /// </summary>
  47. /// <param name="representation">The representation.</param>
  48. /// <param name="converter">The converter.</param>
  49. public DecimalSerializer(BsonType representation, RepresentationConverter converter)
  50. {
  51. switch (representation)
  52. {
  53. case BsonType.Array:
  54. case BsonType.Decimal128:
  55. case BsonType.Double:
  56. case BsonType.Int32:
  57. case BsonType.Int64:
  58. case BsonType.String:
  59. break;
  60. default:
  61. var message = string.Format("{0} is not a valid representation for a DecimalSerializer.", representation);
  62. throw new ArgumentException(message);
  63. }
  64. _representation = representation;
  65. _converter = converter;
  66. }
  67. // public properties
  68. /// <summary>
  69. /// Gets the converter.
  70. /// </summary>
  71. /// <value>
  72. /// The converter.
  73. /// </value>
  74. public RepresentationConverter Converter
  75. {
  76. get { return _converter; }
  77. }
  78. /// <summary>
  79. /// Gets the representation.
  80. /// </summary>
  81. /// <value>
  82. /// The representation.
  83. /// </value>
  84. public BsonType Representation
  85. {
  86. get { return _representation; }
  87. }
  88. // public methods
  89. /// <summary>
  90. /// Deserializes a value.
  91. /// </summary>
  92. /// <param name="context">The deserialization context.</param>
  93. /// <param name="args">The deserialization args.</param>
  94. /// <returns>A deserialized value.</returns>
  95. public override decimal Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
  96. {
  97. var bsonReader = context.Reader;
  98. var bsonType = bsonReader.GetCurrentBsonType();
  99. switch (bsonType)
  100. {
  101. case BsonType.Array:
  102. var array = BsonArraySerializer.Instance.Deserialize(context);
  103. var bits = new int[4];
  104. bits[0] = array[0].AsInt32;
  105. bits[1] = array[1].AsInt32;
  106. bits[2] = array[2].AsInt32;
  107. bits[3] = array[3].AsInt32;
  108. return new decimal(bits);
  109. case BsonType.Decimal128:
  110. return _converter.ToDecimal(bsonReader.ReadDecimal128());
  111. case BsonType.Double:
  112. return _converter.ToDecimal(bsonReader.ReadDouble());
  113. case BsonType.Int32:
  114. return _converter.ToDecimal(bsonReader.ReadInt32());
  115. case BsonType.Int64:
  116. return _converter.ToDecimal(bsonReader.ReadInt64());
  117. case BsonType.String:
  118. return JsonConvert.ToDecimal(bsonReader.ReadString());
  119. default:
  120. throw CreateCannotDeserializeFromBsonTypeException(bsonType);
  121. }
  122. }
  123. /// <summary>
  124. /// Serializes a value.
  125. /// </summary>
  126. /// <param name="context">The serialization context.</param>
  127. /// <param name="args">The serialization args.</param>
  128. /// <param name="value">The object.</param>
  129. public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, decimal value)
  130. {
  131. var bsonWriter = context.Writer;
  132. switch (_representation)
  133. {
  134. case BsonType.Array:
  135. bsonWriter.WriteStartArray();
  136. var bits = Decimal.GetBits(value);
  137. bsonWriter.WriteInt32(bits[0]);
  138. bsonWriter.WriteInt32(bits[1]);
  139. bsonWriter.WriteInt32(bits[2]);
  140. bsonWriter.WriteInt32(bits[3]);
  141. bsonWriter.WriteEndArray();
  142. break;
  143. case BsonType.Decimal128:
  144. bsonWriter.WriteDecimal128(_converter.ToDecimal128(value));
  145. break;
  146. case BsonType.Double:
  147. bsonWriter.WriteDouble(_converter.ToDouble(value));
  148. break;
  149. case BsonType.Int32:
  150. bsonWriter.WriteInt32(_converter.ToInt32(value));
  151. break;
  152. case BsonType.Int64:
  153. bsonWriter.WriteInt64(_converter.ToInt64(value));
  154. break;
  155. case BsonType.String:
  156. bsonWriter.WriteString(JsonConvert.ToString(value));
  157. break;
  158. default:
  159. var message = string.Format("'{0}' is not a valid Decimal representation.", _representation);
  160. throw new BsonSerializationException(message);
  161. }
  162. }
  163. /// <summary>
  164. /// Returns a serializer that has been reconfigured with the specified item serializer.
  165. /// </summary>
  166. /// <param name="converter">The converter.</param>
  167. /// <returns>The reconfigured serializer.</returns>
  168. public DecimalSerializer WithConverter(RepresentationConverter converter)
  169. {
  170. if (converter == _converter)
  171. {
  172. return this;
  173. }
  174. else
  175. {
  176. return new DecimalSerializer(_representation, converter);
  177. }
  178. }
  179. /// <summary>
  180. /// Returns a serializer that has been reconfigured with the specified representation.
  181. /// </summary>
  182. /// <param name="representation">The representation.</param>
  183. /// <returns>The reconfigured serializer.</returns>
  184. public DecimalSerializer WithRepresentation(BsonType representation)
  185. {
  186. if (representation == _representation)
  187. {
  188. return this;
  189. }
  190. else
  191. {
  192. return new DecimalSerializer(representation, _converter);
  193. }
  194. }
  195. // explicit interface implementations
  196. IBsonSerializer IRepresentationConverterConfigurable.WithConverter(RepresentationConverter converter)
  197. {
  198. return WithConverter(converter);
  199. }
  200. IBsonSerializer IRepresentationConfigurable.WithRepresentation(BsonType representation)
  201. {
  202. return WithRepresentation(representation);
  203. }
  204. }
  205. }