You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1591 lines
58 KiB

  1. /* Copyright 2010-2012 10gen 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. using System.Linq;
  18. using System.Text;
  19. using System.Text.RegularExpressions;
  20. using System.Xml;
  21. using MongoDB.Bson.IO;
  22. using MongoDB.Bson.Serialization;
  23. namespace MongoDB.Bson
  24. {
  25. /// <summary>
  26. /// Represents a BSON value (this is an abstract class, see the various subclasses).
  27. /// </summary>
  28. [Serializable]
  29. public abstract class BsonValue : IComparable<BsonValue>, IConvertible, IEquatable<BsonValue>
  30. {
  31. // private static fields
  32. private static Dictionary<BsonType, int> __bsonTypeSortOrder = new Dictionary<BsonType, int>
  33. {
  34. { BsonType.MinKey, 1 },
  35. { BsonType.Undefined, 2 },
  36. { BsonType.Null, 3 },
  37. { BsonType.Double, 4 },
  38. { BsonType.Int32, 4 },
  39. { BsonType.Int64, 4 },
  40. { BsonType.String, 5 },
  41. { BsonType.Symbol, 5 },
  42. { BsonType.Document, 6 },
  43. { BsonType.Array, 7 },
  44. { BsonType.Binary, 8 },
  45. { BsonType.ObjectId, 9 },
  46. { BsonType.Boolean, 10 },
  47. { BsonType.DateTime, 11 },
  48. { BsonType.Timestamp, 11 },
  49. { BsonType.RegularExpression, 12 },
  50. { BsonType.JavaScript, 13 }, // TODO: confirm where JavaScript and JavaScriptWithScope are in the sort order
  51. { BsonType.JavaScriptWithScope, 14 },
  52. { BsonType.MaxKey, 15 }
  53. };
  54. // private fields
  55. private BsonType _bsonType;
  56. // constructors
  57. /// <summary>
  58. /// Initializes a new instance of the BsonValue class.
  59. /// </summary>
  60. /// <param name="bsonType">The BsonType of this BsonValue.</param>
  61. protected BsonValue(BsonType bsonType)
  62. {
  63. _bsonType = bsonType;
  64. }
  65. // public properties
  66. /// <summary>
  67. /// Casts the BsonValue to a Boolean (throws an InvalidCastException if the cast is not valid).
  68. /// </summary>
  69. public bool AsBoolean
  70. {
  71. get { return ((BsonBoolean)this).Value; }
  72. }
  73. /// <summary>
  74. /// Casts the BsonValue to a BsonArray (throws an InvalidCastException if the cast is not valid).
  75. /// </summary>
  76. public BsonArray AsBsonArray
  77. {
  78. get { return (BsonArray)this; }
  79. }
  80. /// <summary>
  81. /// Casts the BsonValue to a BsonBinaryData (throws an InvalidCastException if the cast is not valid).
  82. /// </summary>
  83. public BsonBinaryData AsBsonBinaryData
  84. {
  85. get { return (BsonBinaryData)this; }
  86. }
  87. /// <summary>
  88. /// Casts the BsonValue to a BsonDateTime (throws an InvalidCastException if the cast is not valid).
  89. /// </summary>
  90. public BsonDateTime AsBsonDateTime
  91. {
  92. get { return (BsonDateTime)this; }
  93. }
  94. /// <summary>
  95. /// Casts the BsonValue to a BsonDocument (throws an InvalidCastException if the cast is not valid).
  96. /// </summary>
  97. public BsonDocument AsBsonDocument
  98. {
  99. get { return (BsonDocument)this; }
  100. }
  101. /// <summary>
  102. /// Casts the BsonValue to a BsonJavaScript (throws an InvalidCastException if the cast is not valid).
  103. /// </summary>
  104. public BsonJavaScript AsBsonJavaScript
  105. {
  106. get { return (BsonJavaScript)this; }
  107. }
  108. /// <summary>
  109. /// Casts the BsonValue to a BsonJavaScriptWithScope (throws an InvalidCastException if the cast is not valid).
  110. /// </summary>
  111. public BsonJavaScriptWithScope AsBsonJavaScriptWithScope
  112. {
  113. get { return (BsonJavaScriptWithScope)this; }
  114. }
  115. /// <summary>
  116. /// Casts the BsonValue to a BsonMaxKey (throws an InvalidCastException if the cast is not valid).
  117. /// </summary>
  118. public BsonMaxKey AsBsonMaxKey
  119. {
  120. get { return (BsonMaxKey)this; }
  121. }
  122. /// <summary>
  123. /// Casts the BsonValue to a BsonMinKey (throws an InvalidCastException if the cast is not valid).
  124. /// </summary>
  125. public BsonMinKey AsBsonMinKey
  126. {
  127. get { return (BsonMinKey)this; }
  128. }
  129. /// <summary>
  130. /// Casts the BsonValue to a BsonNull (throws an InvalidCastException if the cast is not valid).
  131. /// </summary>
  132. public BsonNull AsBsonNull
  133. {
  134. get { return (BsonNull)this; }
  135. }
  136. /// <summary>
  137. /// Casts the BsonValue to a BsonRegularExpression (throws an InvalidCastException if the cast is not valid).
  138. /// </summary>
  139. public BsonRegularExpression AsBsonRegularExpression
  140. {
  141. get { return (BsonRegularExpression)this; }
  142. }
  143. /// <summary>
  144. /// Casts the BsonValue to a BsonSymbol (throws an InvalidCastException if the cast is not valid).
  145. /// </summary>
  146. public BsonSymbol AsBsonSymbol
  147. {
  148. get { return (BsonSymbol)this; }
  149. }
  150. /// <summary>
  151. /// Casts the BsonValue to a BsonTimestamp (throws an InvalidCastException if the cast is not valid).
  152. /// </summary>
  153. public BsonTimestamp AsBsonTimestamp
  154. {
  155. get { return (BsonTimestamp)this; }
  156. }
  157. /// <summary>
  158. /// Casts the BsonValue to a BsonUndefined (throws an InvalidCastException if the cast is not valid).
  159. /// </summary>
  160. public BsonUndefined AsBsonUndefined
  161. {
  162. get { return (BsonUndefined)this; }
  163. }
  164. /// <summary>
  165. /// Casts the BsonValue to a BsonValue (a way of upcasting subclasses of BsonValue to BsonValue at compile time).
  166. /// </summary>
  167. public BsonValue AsBsonValue
  168. {
  169. get { return this; }
  170. }
  171. /// <summary>
  172. /// Casts the BsonValue to a Byte[] (throws an InvalidCastException if the cast is not valid).
  173. /// </summary>
  174. public byte[] AsByteArray
  175. {
  176. get { return ((BsonBinaryData)this).Bytes; }
  177. }
  178. /// <summary>
  179. /// Casts the BsonValue to a DateTime in UTC (throws an InvalidCastException if the cast is not valid).
  180. /// </summary>
  181. public DateTime AsDateTime
  182. {
  183. get { return AsUniversalTime; }
  184. }
  185. /// <summary>
  186. /// Casts the BsonValue to a Double (throws an InvalidCastException if the cast is not valid).
  187. /// </summary>
  188. public double AsDouble
  189. {
  190. get { return ((BsonDouble)this).Value; }
  191. }
  192. /// <summary>
  193. /// Casts the BsonValue to a Guid (throws an InvalidCastException if the cast is not valid).
  194. /// </summary>
  195. public Guid AsGuid
  196. {
  197. get { return ((BsonBinaryData)this).ToGuid(); }
  198. }
  199. /// <summary>
  200. /// Casts the BsonValue to an Int32 (throws an InvalidCastException if the cast is not valid).
  201. /// </summary>
  202. public int AsInt32
  203. {
  204. get { return ((BsonInt32)this).Value; }
  205. }
  206. /// <summary>
  207. /// Casts the BsonValue to a DateTime in the local timezone (throws an InvalidCastException if the cast is not valid).
  208. /// </summary>
  209. public DateTime AsLocalTime
  210. {
  211. get { return ((BsonDateTime)this).ToLocalTime(); }
  212. }
  213. /// <summary>
  214. /// Casts the BsonValue to a Int64 (throws an InvalidCastException if the cast is not valid).
  215. /// </summary>
  216. public long AsInt64
  217. {
  218. get { return ((BsonInt64)this).Value; }
  219. }
  220. /// <summary>
  221. /// Casts the BsonValue to a Nullable{Boolean} (throws an InvalidCastException if the cast is not valid).
  222. /// </summary>
  223. public bool? AsNullableBoolean
  224. {
  225. get { return (_bsonType == BsonType.Null) ? null : (bool?)AsBoolean; }
  226. }
  227. /// <summary>
  228. /// Casts the BsonValue to a Nullable{DateTime} (throws an InvalidCastException if the cast is not valid).
  229. /// </summary>
  230. public DateTime? AsNullableDateTime
  231. {
  232. get { return (_bsonType == BsonType.Null) ? null : (DateTime?)AsDateTime; }
  233. }
  234. /// <summary>
  235. /// Casts the BsonValue to a Nullable{Double} (throws an InvalidCastException if the cast is not valid).
  236. /// </summary>
  237. public double? AsNullableDouble
  238. {
  239. get { return (_bsonType == BsonType.Null) ? null : (double?)AsDouble; }
  240. }
  241. /// <summary>
  242. /// Casts the BsonValue to a Nullable{Guid} (throws an InvalidCastException if the cast is not valid).
  243. /// </summary>
  244. public Guid? AsNullableGuid
  245. {
  246. get { return (_bsonType == BsonType.Null) ? null : (Guid?)AsGuid; }
  247. }
  248. /// <summary>
  249. /// Casts the BsonValue to a Nullable{Int32} (throws an InvalidCastException if the cast is not valid).
  250. /// </summary>
  251. public int? AsNullableInt32
  252. {
  253. get { return (_bsonType == BsonType.Null) ? null : (int?)AsInt32; }
  254. }
  255. /// <summary>
  256. /// Casts the BsonValue to a Nullable{Int64} (throws an InvalidCastException if the cast is not valid).
  257. /// </summary>
  258. public long? AsNullableInt64
  259. {
  260. get { return (_bsonType == BsonType.Null) ? null : (long?)AsInt64; }
  261. }
  262. /// <summary>
  263. /// Casts the BsonValue to a Nullable{ObjectId} (throws an InvalidCastException if the cast is not valid).
  264. /// </summary>
  265. public ObjectId? AsNullableObjectId
  266. {
  267. get { return (_bsonType == BsonType.Null) ? null : (ObjectId?)AsObjectId; }
  268. }
  269. /// <summary>
  270. /// Casts the BsonValue to an ObjectId (throws an InvalidCastException if the cast is not valid).
  271. /// </summary>
  272. public ObjectId AsObjectId
  273. {
  274. get { return ((BsonObjectId)this).Value; }
  275. }
  276. /// <summary>
  277. /// Casts the BsonValue to a Regex (throws an InvalidCastException if the cast is not valid).
  278. /// </summary>
  279. public Regex AsRegex
  280. {
  281. get { return ((BsonRegularExpression)this).ToRegex(); }
  282. }
  283. /// <summary>
  284. /// Casts the BsonValue to a String (throws an InvalidCastException if the cast is not valid).
  285. /// </summary>
  286. public string AsString
  287. {
  288. get { return ((BsonString)this).Value; }
  289. }
  290. /// <summary>
  291. /// Casts the BsonValue to a DateTime in UTC (throws an InvalidCastException if the cast is not valid).
  292. /// </summary>
  293. public DateTime AsUniversalTime
  294. {
  295. get { return ((BsonDateTime)this).ToUniversalTime(); }
  296. }
  297. /// <summary>
  298. /// Gets the BsonType of this BsonValue.
  299. /// </summary>
  300. public BsonType BsonType
  301. {
  302. get { return _bsonType; }
  303. }
  304. /// <summary>
  305. /// Tests whether this BsonValue is a Boolean.
  306. /// </summary>
  307. public bool IsBoolean
  308. {
  309. get { return _bsonType == BsonType.Boolean; }
  310. }
  311. /// <summary>
  312. /// Tests whether this BsonValue is a BsonArray.
  313. /// </summary>
  314. public bool IsBsonArray
  315. {
  316. get { return _bsonType == BsonType.Array; }
  317. }
  318. /// <summary>
  319. /// Tests whether this BsonValue is a BsonBinaryData.
  320. /// </summary>
  321. public bool IsBsonBinaryData
  322. {
  323. get { return _bsonType == BsonType.Binary; }
  324. }
  325. /// <summary>
  326. /// Tests whether this BsonValue is a BsonDateTime.
  327. /// </summary>
  328. public bool IsBsonDateTime
  329. {
  330. get { return _bsonType == BsonType.DateTime; }
  331. }
  332. /// <summary>
  333. /// Tests whether this BsonValue is a BsonDocument.
  334. /// </summary>
  335. public bool IsBsonDocument
  336. {
  337. get { return _bsonType == BsonType.Document; }
  338. }
  339. /// <summary>
  340. /// Tests whether this BsonValue is a BsonJavaScript.
  341. /// </summary>
  342. public bool IsBsonJavaScript
  343. {
  344. get { return _bsonType == BsonType.JavaScript || _bsonType == BsonType.JavaScriptWithScope; }
  345. }
  346. /// <summary>
  347. /// Tests whether this BsonValue is a BsonJavaScriptWithScope.
  348. /// </summary>
  349. public bool IsBsonJavaScriptWithScope
  350. {
  351. get { return _bsonType == BsonType.JavaScriptWithScope; }
  352. }
  353. /// <summary>
  354. /// Tests whether this BsonValue is a BsonMaxKey.
  355. /// </summary>
  356. public bool IsBsonMaxKey
  357. {
  358. get { return _bsonType == BsonType.MaxKey; }
  359. }
  360. /// <summary>
  361. /// Tests whether this BsonValue is a BsonMinKey.
  362. /// </summary>
  363. public bool IsBsonMinKey
  364. {
  365. get { return _bsonType == BsonType.MinKey; }
  366. }
  367. /// <summary>
  368. /// Tests whether this BsonValue is a BsonNull.
  369. /// </summary>
  370. public bool IsBsonNull
  371. {
  372. get { return _bsonType == BsonType.Null; }
  373. }
  374. /// <summary>
  375. /// Tests whether this BsonValue is a BsonRegularExpression.
  376. /// </summary>
  377. public bool IsBsonRegularExpression
  378. {
  379. get { return _bsonType == BsonType.RegularExpression; }
  380. }
  381. /// <summary>
  382. /// Tests whether this BsonValue is a BsonSymbol .
  383. /// </summary>
  384. public bool IsBsonSymbol
  385. {
  386. get { return _bsonType == BsonType.Symbol; }
  387. }
  388. /// <summary>
  389. /// Tests whether this BsonValue is a BsonTimestamp.
  390. /// </summary>
  391. public bool IsBsonTimestamp
  392. {
  393. get { return _bsonType == BsonType.Timestamp; }
  394. }
  395. /// <summary>
  396. /// Tests whether this BsonValue is a BsonUndefined.
  397. /// </summary>
  398. public bool IsBsonUndefined
  399. {
  400. get { return _bsonType == BsonType.Undefined; }
  401. }
  402. /// <summary>
  403. /// Tests whether this BsonValue is a DateTime.
  404. /// </summary>
  405. public bool IsDateTime
  406. {
  407. get { return _bsonType == BsonType.DateTime && ((BsonDateTime)this).IsValidDateTime; }
  408. }
  409. /// <summary>
  410. /// Tests whether this BsonValue is a Double.
  411. /// </summary>
  412. public bool IsDouble
  413. {
  414. get { return _bsonType == BsonType.Double; }
  415. }
  416. /// <summary>
  417. /// Tests whether this BsonValue is a Guid.
  418. /// </summary>
  419. public bool IsGuid
  420. {
  421. get
  422. {
  423. if (_bsonType == BsonType.Binary)
  424. {
  425. var subType = ((BsonBinaryData)this).SubType;
  426. return subType == BsonBinarySubType.UuidStandard || subType == BsonBinarySubType.UuidLegacy;
  427. }
  428. else
  429. {
  430. return false;
  431. }
  432. }
  433. }
  434. /// <summary>
  435. /// Tests whether this BsonValue is an Int32.
  436. /// </summary>
  437. public bool IsInt32
  438. {
  439. get { return _bsonType == BsonType.Int32; }
  440. }
  441. /// <summary>
  442. /// Tests whether this BsonValue is an Int64.
  443. /// </summary>
  444. public bool IsInt64
  445. {
  446. get { return _bsonType == BsonType.Int64; }
  447. }
  448. /// <summary>
  449. /// Tests whether this BsonValue is a numeric value.
  450. /// </summary>
  451. public bool IsNumeric
  452. {
  453. get
  454. {
  455. return
  456. _bsonType == BsonType.Double ||
  457. _bsonType == BsonType.Int32 ||
  458. _bsonType == BsonType.Int64;
  459. }
  460. }
  461. /// <summary>
  462. /// Tests whether this BsonValue is an ObjectId .
  463. /// </summary>
  464. public bool IsObjectId
  465. {
  466. get { return _bsonType == BsonType.ObjectId; }
  467. }
  468. /// <summary>
  469. /// Tests whether this BsonValue is a String.
  470. /// </summary>
  471. public bool IsString
  472. {
  473. get { return _bsonType == BsonType.String; }
  474. }
  475. /// <summary>
  476. /// Gets the raw value of this BsonValue (or null if this BsonValue doesn't have a single scalar value).
  477. /// </summary>
  478. // note: don't change return value to "this" or lots of things will break
  479. public virtual object RawValue
  480. {
  481. get { return null; } // subclasses that have a single value (e.g. Int32) override this
  482. }
  483. // public operators
  484. /// <summary>
  485. /// Casts a BsonValue to a bool.
  486. /// </summary>
  487. /// <param name="value">The BsonValue.</param>
  488. /// <returns>A bool.</returns>
  489. public static explicit operator bool(BsonValue value)
  490. {
  491. if (value == null)
  492. {
  493. throw new ArgumentNullException("value");
  494. }
  495. return value.AsBoolean;
  496. }
  497. /// <summary>
  498. /// Casts a BsonValue to a bool?.
  499. /// </summary>
  500. /// <param name="value">The BsonValue.</param>
  501. /// <returns>A bool?.</returns>
  502. public static explicit operator bool?(BsonValue value)
  503. {
  504. return (value == null) ? null : value.AsNullableBoolean;
  505. }
  506. /// <summary>
  507. /// Converts a bool to a BsonValue.
  508. /// </summary>
  509. /// <param name="value">A bool.</param>
  510. /// <returns>A BsonValue.</returns>
  511. public static implicit operator BsonValue(bool value)
  512. {
  513. return BsonBoolean.Create(value);
  514. }
  515. /// <summary>
  516. /// Converts a bool? to a BsonValue.
  517. /// </summary>
  518. /// <param name="value">A bool?.</param>
  519. /// <returns>A BsonValue.</returns>
  520. public static implicit operator BsonValue(bool? value)
  521. {
  522. return value.HasValue ? (BsonValue)BsonBoolean.Create(value.Value) : BsonNull.Value;
  523. }
  524. /// <summary>
  525. /// Converts a byte[] to a BsonValue.
  526. /// </summary>
  527. /// <param name="value">A byte[].</param>
  528. /// <returns>A BsonValue.</returns>
  529. public static implicit operator BsonValue(byte[] value)
  530. {
  531. return BsonBinaryData.Create(value);
  532. }
  533. /// <summary>
  534. /// Converts a DateTime to a BsonValue.
  535. /// </summary>
  536. /// <param name="value">A DateTime.</param>
  537. /// <returns>A BsonValue.</returns>
  538. public static implicit operator BsonValue(DateTime value)
  539. {
  540. return new BsonDateTime(value);
  541. }
  542. /// <summary>
  543. /// Converts a DateTime? to a BsonValue.
  544. /// </summary>
  545. /// <param name="value">A DateTime?.</param>
  546. /// <returns>A BsonValue.</returns>
  547. public static implicit operator BsonValue(DateTime? value)
  548. {
  549. return value.HasValue ? (BsonValue)BsonDateTime.Create(value.Value) : BsonNull.Value;
  550. }
  551. /// <summary>
  552. /// Converts a double to a BsonValue.
  553. /// </summary>
  554. /// <param name="value">A double.</param>
  555. /// <returns>A BsonValue.</returns>
  556. public static implicit operator BsonValue(double value)
  557. {
  558. return new BsonDouble(value);
  559. }
  560. /// <summary>
  561. /// Converts a double? to a BsonValue.
  562. /// </summary>
  563. /// <param name="value">A double?.</param>
  564. /// <returns>A BsonValue.</returns>
  565. public static implicit operator BsonValue(double? value)
  566. {
  567. return value.HasValue ? (BsonValue)BsonDouble.Create(value.Value) : BsonNull.Value;
  568. }
  569. /// <summary>
  570. /// Converts an Enum to a BsonValue.
  571. /// </summary>
  572. /// <param name="value">An Enum.</param>
  573. /// <returns>A BsonValue.</returns>
  574. public static implicit operator BsonValue(Enum value)
  575. {
  576. return BsonTypeMapper.MapToBsonValue(value);
  577. }
  578. /// <summary>
  579. /// Converts a Guid to a BsonValue.
  580. /// </summary>
  581. /// <param name="value">A Guid.</param>
  582. /// <returns>A BsonValue.</returns>
  583. public static implicit operator BsonValue(Guid value)
  584. {
  585. return BsonBinaryData.Create(value);
  586. }
  587. /// <summary>
  588. /// Converts a Guid? to a BsonValue.
  589. /// </summary>
  590. /// <param name="value">A Guid?.</param>
  591. /// <returns>A BsonValue.</returns>
  592. public static implicit operator BsonValue(Guid? value)
  593. {
  594. return value.HasValue ? (BsonValue)BsonBinaryData.Create(value.Value) : BsonNull.Value;
  595. }
  596. /// <summary>
  597. /// Converts an int to a BsonValue.
  598. /// </summary>
  599. /// <param name="value">An int.</param>
  600. /// <returns>A BsonValue.</returns>
  601. public static implicit operator BsonValue(int value)
  602. {
  603. return BsonInt32.Create(value);
  604. }
  605. /// <summary>
  606. /// Converts an int? to a BsonValue.
  607. /// </summary>
  608. /// <param name="value">An int?.</param>
  609. /// <returns>A BsonValue.</returns>
  610. public static implicit operator BsonValue(int? value)
  611. {
  612. return value.HasValue ? (BsonValue)BsonInt32.Create(value.Value) : BsonNull.Value;
  613. }
  614. /// <summary>
  615. /// Converts a long to a BsonValue.
  616. /// </summary>
  617. /// <param name="value">A long.</param>
  618. /// <returns>A BsonValue.</returns>
  619. public static implicit operator BsonValue(long value)
  620. {
  621. return new BsonInt64(value);
  622. }
  623. /// <summary>
  624. /// Converts a long? to a BsonValue.
  625. /// </summary>
  626. /// <param name="value">A long?.</param>
  627. /// <returns>A BsonValue.</returns>
  628. public static implicit operator BsonValue(long? value)
  629. {
  630. return value.HasValue ? (BsonValue)BsonInt64.Create(value.Value) : BsonNull.Value;
  631. }
  632. /// <summary>
  633. /// Converts an ObjectId to a BsonValue.
  634. /// </summary>
  635. /// <param name="value">An ObjectId.</param>
  636. /// <returns>A BsonValue.</returns>
  637. public static implicit operator BsonValue(ObjectId value)
  638. {
  639. return new BsonObjectId(value);
  640. }
  641. /// <summary>
  642. /// Converts an ObjectId? to a BsonValue.
  643. /// </summary>
  644. /// <param name="value">An ObjectId?.</param>
  645. /// <returns>A BsonValue.</returns>
  646. public static implicit operator BsonValue(ObjectId? value)
  647. {
  648. return value.HasValue ? (BsonValue)BsonObjectId.Create(value.Value) : BsonNull.Value;
  649. }
  650. /// <summary>
  651. /// Converts a Regex to a BsonValue.
  652. /// </summary>
  653. /// <param name="value">A Regex.</param>
  654. /// <returns>A BsonValue.</returns>
  655. public static implicit operator BsonValue(Regex value)
  656. {
  657. return BsonRegularExpression.Create(value);
  658. }
  659. /// <summary>
  660. /// Converts a string to a BsonValue.
  661. /// </summary>
  662. /// <param name="value">A string.</param>
  663. /// <returns>A BsonValue.</returns>
  664. public static implicit operator BsonValue(string value)
  665. {
  666. return BsonString.Create(value);
  667. }
  668. /// <summary>
  669. /// Casts a BsonValue to a byte[].
  670. /// </summary>
  671. /// <param name="value">The BsonValue.</param>
  672. /// <returns>A byte[].</returns>
  673. public static explicit operator byte[](BsonValue value)
  674. {
  675. return (value == null) ? null : value.AsByteArray;
  676. }
  677. /// <summary>
  678. /// Casts a BsonValue to a DateTime.
  679. /// </summary>
  680. /// <param name="value">The BsonValue.</param>
  681. /// <returns>A DateTime.</returns>
  682. public static explicit operator DateTime(BsonValue value)
  683. {
  684. if (value == null)
  685. {
  686. throw new ArgumentNullException("value");
  687. }
  688. return value.AsDateTime;
  689. }
  690. /// <summary>
  691. /// Casts a BsonValue to a DateTime?.
  692. /// </summary>
  693. /// <param name="value">The BsonValue.</param>
  694. /// <returns>A DateTime?.</returns>
  695. public static explicit operator DateTime?(BsonValue value)
  696. {
  697. return (value == null) ? null : value.AsNullableDateTime;
  698. }
  699. /// <summary>
  700. /// Casts a BsonValue to a double.
  701. /// </summary>
  702. /// <param name="value">The BsonValue.</param>
  703. /// <returns>A double.</returns>
  704. public static explicit operator double(BsonValue value)
  705. {
  706. if (value == null)
  707. {
  708. throw new ArgumentNullException("value");
  709. }
  710. return value.AsDouble;
  711. }
  712. /// <summary>
  713. /// Casts a BsonValue to a double?.
  714. /// </summary>
  715. /// <param name="value">The BsonValue.</param>
  716. /// <returns>A double?.</returns>
  717. public static explicit operator double?(BsonValue value)
  718. {
  719. return (value == null) ? null : value.AsNullableDouble;
  720. }
  721. /// <summary>
  722. /// Casts a BsonValue to a Guid.
  723. /// </summary>
  724. /// <param name="value">The BsonValue.</param>
  725. /// <returns>A Guid.</returns>
  726. public static explicit operator Guid(BsonValue value)
  727. {
  728. if (value == null)
  729. {
  730. throw new ArgumentNullException("value");
  731. }
  732. return value.AsGuid;
  733. }
  734. /// <summary>
  735. /// Casts a BsonValue to a Guid?.
  736. /// </summary>
  737. /// <param name="value">The BsonValue.</param>
  738. /// <returns>A Guid?.</returns>
  739. public static explicit operator Guid?(BsonValue value)
  740. {
  741. return (value == null) ? null : value.AsNullableGuid;
  742. }
  743. /// <summary>
  744. /// Casts a BsonValue to an int.
  745. /// </summary>
  746. /// <param name="value">The BsonValue.</param>
  747. /// <returns>An int.</returns>
  748. public static explicit operator int(BsonValue value)
  749. {
  750. if (value == null)
  751. {
  752. throw new ArgumentNullException("value");
  753. }
  754. return value.AsInt32;
  755. }
  756. /// <summary>
  757. /// Casts a BsonValue to an int?.
  758. /// </summary>
  759. /// <param name="value">The BsonValue.</param>
  760. /// <returns>An int?.</returns>
  761. public static explicit operator int?(BsonValue value)
  762. {
  763. return value == null ? null : value.AsNullableInt32;
  764. }
  765. /// <summary>
  766. /// Casts a BsonValue to a long.
  767. /// </summary>
  768. /// <param name="value">The BsonValue.</param>
  769. /// <returns>A long.</returns>
  770. public static explicit operator long(BsonValue value)
  771. {
  772. if (value == null)
  773. {
  774. throw new ArgumentNullException("value");
  775. }
  776. return value.AsInt64;
  777. }
  778. /// <summary>
  779. /// Casts a BsonValue to a long?.
  780. /// </summary>
  781. /// <param name="value">The BsonValue.</param>
  782. /// <returns>A long?.</returns>
  783. public static explicit operator long?(BsonValue value)
  784. {
  785. return (value == null) ? null : value.AsNullableInt64;
  786. }
  787. /// <summary>
  788. /// Casts a BsonValue to an ObjectId.
  789. /// </summary>
  790. /// <param name="value">The BsonValue.</param>
  791. /// <returns>An ObjectId.</returns>
  792. public static explicit operator ObjectId(BsonValue value)
  793. {
  794. if (value == null)
  795. {
  796. throw new ArgumentNullException("value");
  797. }
  798. return value.AsObjectId;
  799. }
  800. /// <summary>
  801. /// Casts a BsonValue to an ObjectId?.
  802. /// </summary>
  803. /// <param name="value">The BsonValue.</param>
  804. /// <returns>An ObjectId?.</returns>
  805. public static explicit operator ObjectId?(BsonValue value)
  806. {
  807. return (value == null) ? null : value.AsNullableObjectId;
  808. }
  809. /// <summary>
  810. /// Casts a BsonValue to a Regex.
  811. /// </summary>
  812. /// <param name="value">The BsonValue.</param>
  813. /// <returns>A Regex.</returns>
  814. public static explicit operator Regex(BsonValue value)
  815. {
  816. return (value == null) ? null : value.AsRegex;
  817. }
  818. /// <summary>
  819. /// Casts a BsonValue to a string.
  820. /// </summary>
  821. /// <param name="value">The BsonValue.</param>
  822. /// <returns>A string.</returns>
  823. public static explicit operator string(BsonValue value)
  824. {
  825. return (value == null) ? null : value.AsString;
  826. }
  827. /// <summary>
  828. /// Compares two BsonValues.
  829. /// </summary>
  830. /// <param name="lhs">The first BsonValue.</param>
  831. /// <param name="rhs">The other BsonValue.</param>
  832. /// <returns>True if the first BsonValue is less than the other one.</returns>
  833. public static bool operator <(BsonValue lhs, BsonValue rhs)
  834. {
  835. if (object.ReferenceEquals(lhs, null) && object.ReferenceEquals(rhs, null)) { return false; }
  836. if (object.ReferenceEquals(lhs, null)) { return true; }
  837. if (object.ReferenceEquals(rhs, null)) { return false; }
  838. return lhs.CompareTo(rhs) < 0;
  839. }
  840. /// <summary>
  841. /// Compares two BsonValues.
  842. /// </summary>
  843. /// <param name="lhs">The first BsonValue.</param>
  844. /// <param name="rhs">The other BsonValue.</param>
  845. /// <returns>True if the first BsonValue is less than or equal to the other one.</returns>
  846. public static bool operator <=(BsonValue lhs, BsonValue rhs)
  847. {
  848. if (object.ReferenceEquals(lhs, null) && object.ReferenceEquals(rhs, null)) { return true; }
  849. if (object.ReferenceEquals(lhs, null)) { return true; }
  850. if (object.ReferenceEquals(rhs, null)) { return false; }
  851. return lhs.CompareTo(rhs) <= 0;
  852. }
  853. /// <summary>
  854. /// Compares two BsonValues.
  855. /// </summary>
  856. /// <param name="lhs">The first BsonValue.</param>
  857. /// <param name="rhs">The other BsonValue.</param>
  858. /// <returns>True if the two BsonValues are not equal according to ==.</returns>
  859. public static bool operator !=(BsonValue lhs, BsonValue rhs)
  860. {
  861. return !(lhs == rhs);
  862. }
  863. /// <summary>
  864. /// Compares two BsonValues.
  865. /// </summary>
  866. /// <param name="lhs">The first BsonValue.</param>
  867. /// <param name="rhs">The other BsonValue.</param>
  868. /// <returns>True if the two BsonValues are equal according to ==.</returns>
  869. public static bool operator ==(BsonValue lhs, BsonValue rhs)
  870. {
  871. if (object.ReferenceEquals(lhs, null)) { return object.ReferenceEquals(rhs, null); }
  872. if (object.ReferenceEquals(rhs, null)) { return false; } // don't check type because sometimes different types can be ==
  873. return lhs.OperatorEqualsImplementation(rhs); // some subclasses override OperatorEqualsImplementation
  874. }
  875. /// <summary>
  876. /// Compares two BsonValues.
  877. /// </summary>
  878. /// <param name="lhs">The first BsonValue.</param>
  879. /// <param name="rhs">The other BsonValue.</param>
  880. /// <returns>True if the first BsonValue is greater than the other one.</returns>
  881. public static bool operator >(BsonValue lhs, BsonValue rhs)
  882. {
  883. return !(lhs <= rhs);
  884. }
  885. /// <summary>
  886. /// Compares two BsonValues.
  887. /// </summary>
  888. /// <param name="lhs">The first BsonValue.</param>
  889. /// <param name="rhs">The other BsonValue.</param>
  890. /// <returns>True if the first BsonValue is greater than or equal to the other one.</returns>
  891. public static bool operator >=(BsonValue lhs, BsonValue rhs)
  892. {
  893. return !(lhs < rhs);
  894. }
  895. // public static methods
  896. // TODO: implement more Create methods for .NET types (int, string, etc...)? Not sure... already have implicit conversions
  897. /// <summary>
  898. /// Creates a new instance of the BsonValue class.
  899. /// </summary>
  900. /// <param name="value">A value to be mapped to a BsonValue.</param>
  901. /// <returns>A BsonValue.</returns>
  902. public static BsonValue Create(object value)
  903. {
  904. // optimize away the call to MapToBsonValue for the most common cases
  905. if (value == null)
  906. {
  907. return null; // not BsonNull.Value to be consistent with other Create methods
  908. }
  909. else if (value is BsonValue)
  910. {
  911. return (BsonValue)value;
  912. }
  913. else if (value is int)
  914. {
  915. return BsonInt32.Create((int)value);
  916. }
  917. else if (value is string)
  918. {
  919. return new BsonString((string)value);
  920. }
  921. else if (value is bool)
  922. {
  923. return BsonBoolean.Create((bool)value);
  924. }
  925. else if (value is DateTime)
  926. {
  927. return new BsonDateTime((DateTime)value);
  928. }
  929. else if (value is long)
  930. {
  931. return new BsonInt64((long)value);
  932. }
  933. else if (value is double)
  934. {
  935. return new BsonDouble((double)value);
  936. }
  937. else
  938. {
  939. return BsonTypeMapper.MapToBsonValue(value);
  940. }
  941. }
  942. /// <summary>
  943. /// Reads one BsonValue from a BsonReader.
  944. /// </summary>
  945. /// <param name="bsonReader">The reader.</param>
  946. /// <returns>A BsonValue.</returns>
  947. public static BsonValue ReadFrom(BsonReader bsonReader)
  948. {
  949. BsonType bsonType = bsonReader.GetCurrentBsonType();
  950. switch (bsonType)
  951. {
  952. case BsonType.Array:
  953. return BsonArray.ReadFrom(bsonReader);
  954. case BsonType.Binary:
  955. byte[] bytes;
  956. BsonBinarySubType subType;
  957. GuidRepresentation guidRepresentation;
  958. bsonReader.ReadBinaryData(out bytes, out subType, out guidRepresentation);
  959. return new BsonBinaryData(bytes, subType, guidRepresentation);
  960. case BsonType.Boolean:
  961. return BsonBoolean.Create(bsonReader.ReadBoolean());
  962. case BsonType.DateTime:
  963. return new BsonDateTime(bsonReader.ReadDateTime());
  964. case BsonType.Document:
  965. return BsonDocument.ReadFrom(bsonReader);
  966. case BsonType.Double:
  967. return new BsonDouble(bsonReader.ReadDouble());
  968. case BsonType.Int32:
  969. return BsonInt32.Create(bsonReader.ReadInt32());
  970. case BsonType.Int64:
  971. return new BsonInt64(bsonReader.ReadInt64());
  972. case BsonType.JavaScript:
  973. return new BsonJavaScript(bsonReader.ReadJavaScript());
  974. case BsonType.JavaScriptWithScope:
  975. string code = bsonReader.ReadJavaScriptWithScope();
  976. var scope = BsonDocument.ReadFrom(bsonReader);
  977. return new BsonJavaScriptWithScope(code, scope);
  978. case BsonType.MaxKey:
  979. bsonReader.ReadMaxKey();
  980. return BsonMaxKey.Value;
  981. case BsonType.MinKey:
  982. bsonReader.ReadMinKey();
  983. return BsonMinKey.Value;
  984. case BsonType.Null:
  985. bsonReader.ReadNull();
  986. return BsonNull.Value;
  987. case BsonType.ObjectId:
  988. int timestamp;
  989. int machine;
  990. short pid;
  991. int increment;
  992. bsonReader.ReadObjectId(out timestamp, out machine, out pid, out increment);
  993. return new BsonObjectId(timestamp, machine, pid, increment);
  994. case BsonType.RegularExpression:
  995. string pattern;
  996. string options;
  997. bsonReader.ReadRegularExpression(out pattern, out options);
  998. return new BsonRegularExpression(pattern, options);
  999. case BsonType.String:
  1000. return new BsonString(bsonReader.ReadString());
  1001. case BsonType.Symbol:
  1002. return BsonSymbol.Create(bsonReader.ReadSymbol());
  1003. case BsonType.Timestamp:
  1004. return new BsonTimestamp(bsonReader.ReadTimestamp());
  1005. case BsonType.Undefined:
  1006. bsonReader.ReadUndefined();
  1007. return BsonUndefined.Value;
  1008. default:
  1009. var message = string.Format("Invalid BsonType {0}.", bsonType);
  1010. throw new BsonInternalException(message);
  1011. }
  1012. }
  1013. // public methods
  1014. /// <summary>
  1015. /// Creates a shallow clone of the BsonValue (see also DeepClone).
  1016. /// </summary>
  1017. /// <returns>A shallow clone of the BsonValue.</returns>
  1018. public virtual BsonValue Clone()
  1019. {
  1020. return this; // subclasses override Clone if necessary
  1021. }
  1022. /// <summary>
  1023. /// Compares this BsonValue to another BsonValue.
  1024. /// </summary>
  1025. /// <param name="other">The other BsonValue.</param>
  1026. /// <returns>A 32-bit signed integer that indicates whether this BsonValue is less than, equal to, or greather than the other BsonValue.</returns>
  1027. public abstract int CompareTo(BsonValue other);
  1028. /// <summary>
  1029. /// Compares the type of this BsonValue to the type of another BsonValue.
  1030. /// </summary>
  1031. /// <param name="other">The other BsonValue.</param>
  1032. /// <returns>A 32-bit signed integer that indicates whether the type of this BsonValue is less than, equal to, or greather than the type of the other BsonValue.</returns>
  1033. public int CompareTypeTo(BsonValue other)
  1034. {
  1035. if (object.ReferenceEquals(other, null)) { return 1; }
  1036. return __bsonTypeSortOrder[_bsonType].CompareTo(__bsonTypeSortOrder[other._bsonType]);
  1037. }
  1038. /// <summary>
  1039. /// Creates a deep clone of the BsonValue (see also Clone).
  1040. /// </summary>
  1041. /// <returns>A deep clone of the BsonValue.</returns>
  1042. public virtual BsonValue DeepClone()
  1043. {
  1044. return this; // subclasses override DeepClone if necessary
  1045. }
  1046. /// <summary>
  1047. /// Compares this BsonValue to another BsonValue.
  1048. /// </summary>
  1049. /// <param name="rhs">The other BsonValue.</param>
  1050. /// <returns>True if the two BsonValue values are equal.</returns>
  1051. public bool Equals(BsonValue rhs)
  1052. {
  1053. return Equals((object)rhs);
  1054. }
  1055. /// <summary>
  1056. /// Compares this BsonValue to another object.
  1057. /// </summary>
  1058. /// <param name="obj">The other object.</param>
  1059. /// <returns>True if the other object is a BsonValue and equal to this one.</returns>
  1060. public override bool Equals(object obj)
  1061. {
  1062. throw new BsonInternalException("A subclass of BsonValue did not override Equals.");
  1063. }
  1064. /// <summary>
  1065. /// Gets the hash code.
  1066. /// </summary>
  1067. /// <returns>The hash code.</returns>
  1068. public override int GetHashCode()
  1069. {
  1070. throw new BsonInternalException("A subclass of BsonValue did not override GetHashCode.");
  1071. }
  1072. /// <summary>
  1073. /// Converts this BsonValue to a Boolean (using the JavaScript definition of truthiness).
  1074. /// </summary>
  1075. /// <returns>A Boolean.</returns>
  1076. public bool ToBoolean()
  1077. {
  1078. switch (_bsonType)
  1079. {
  1080. case BsonType.Boolean: return ((BsonBoolean)this).Value;
  1081. case BsonType.Double: var d = ((BsonDouble)this).Value; return !(double.IsNaN(d) || d == 0.0);
  1082. case BsonType.Int32: return ((BsonInt32)this).Value != 0;
  1083. case BsonType.Int64: return ((BsonInt64)this).Value != 0;
  1084. case BsonType.Null: return false;
  1085. case BsonType.String: return ((BsonString)this).Value != "";
  1086. case BsonType.Undefined: return false;
  1087. default: return true; // everything else is true
  1088. }
  1089. }
  1090. /// <summary>
  1091. /// Converts this BsonValue to a Double.
  1092. /// </summary>
  1093. /// <returns>A Double.</returns>
  1094. public double ToDouble()
  1095. {
  1096. switch (_bsonType)
  1097. {
  1098. case BsonType.Int32: return (double)((BsonInt32)this).Value;
  1099. case BsonType.Int64: return (double)((BsonInt64)this).Value;
  1100. case BsonType.String: return XmlConvert.ToDouble(((BsonString)this).Value);
  1101. default: return ((BsonDouble)this).Value;
  1102. }
  1103. }
  1104. /// <summary>
  1105. /// Converts this BsonValue to an Int32.
  1106. /// </summary>
  1107. /// <returns>An Int32.</returns>
  1108. public int ToInt32()
  1109. {
  1110. switch (_bsonType)
  1111. {
  1112. case BsonType.Double: return (int)((BsonDouble)this).Value;
  1113. case BsonType.Int64: return (int)((BsonInt64)this).Value;
  1114. case BsonType.String: return XmlConvert.ToInt32(((BsonString)this).Value);
  1115. default: return ((BsonInt32)this).Value;
  1116. }
  1117. }
  1118. /// <summary>
  1119. /// Converts this BsonValue to an Int64.
  1120. /// </summary>
  1121. /// <returns>An Int64.</returns>
  1122. public long ToInt64()
  1123. {
  1124. switch (_bsonType)
  1125. {
  1126. case BsonType.Double: return (long)((BsonDouble)this).Value;
  1127. case BsonType.Int32: return (long)((BsonInt32)this).Value;
  1128. case BsonType.String: return XmlConvert.ToInt64(((BsonString)this).Value);
  1129. default: return ((BsonInt64)this).Value;
  1130. }
  1131. }
  1132. /// <summary>
  1133. /// Writes the BsonValue to a BsonWriter.
  1134. /// </summary>
  1135. /// <param name="bsonWriter">The writer.</param>
  1136. public void WriteTo(BsonWriter bsonWriter)
  1137. {
  1138. switch (_bsonType)
  1139. {
  1140. case BsonType.Array:
  1141. ((BsonArray)this).WriteTo(bsonWriter);
  1142. break;
  1143. case BsonType.Binary:
  1144. var binaryData = (BsonBinaryData)this;
  1145. var bytes = binaryData.Bytes;
  1146. var subType = binaryData.SubType;
  1147. var guidRepresentation = binaryData.GuidRepresentation;
  1148. var writerGuidRepresentation = bsonWriter.Settings.GuidRepresentation;
  1149. if (subType == BsonBinarySubType.UuidLegacy && writerGuidRepresentation != GuidRepresentation.Unspecified)
  1150. {
  1151. if (guidRepresentation != writerGuidRepresentation)
  1152. {
  1153. if (guidRepresentation == GuidRepresentation.Unspecified)
  1154. {
  1155. var message = string.Format("Cannot write binary data of sub type UuidLegacy and GuidRepresentation Unspecified to a collection with GuidRepresentation {0}.", writerGuidRepresentation);
  1156. throw new BsonSerializationException(message);
  1157. }
  1158. var guid = GuidConverter.FromBytes(bytes, guidRepresentation);
  1159. bytes = GuidConverter.ToBytes(guid, writerGuidRepresentation);
  1160. subType = (writerGuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
  1161. guidRepresentation = writerGuidRepresentation;
  1162. }
  1163. }
  1164. bsonWriter.WriteBinaryData(bytes, subType, guidRepresentation);
  1165. break;
  1166. case BsonType.Boolean:
  1167. bsonWriter.WriteBoolean(((BsonBoolean)this).Value);
  1168. break;
  1169. case BsonType.DateTime:
  1170. bsonWriter.WriteDateTime(((BsonDateTime)this).MillisecondsSinceEpoch);
  1171. break;
  1172. case BsonType.Document:
  1173. var document = this as BsonDocument;
  1174. if (document != null)
  1175. {
  1176. document.WriteTo(bsonWriter);
  1177. }
  1178. else
  1179. {
  1180. var documentWrapper = this as BsonDocumentWrapper;
  1181. if (documentWrapper != null)
  1182. {
  1183. ((IBsonSerializable)documentWrapper).Serialize(bsonWriter, typeof(BsonDocument), null);
  1184. }
  1185. else
  1186. {
  1187. var message = string.Format("BsonType Document can only be used with the classes BsonDocument or BsonDocumentWrapper, not with the class {0}.", this.GetType().FullName);
  1188. throw new BsonInternalException(message);
  1189. }
  1190. }
  1191. break;
  1192. case BsonType.Double:
  1193. bsonWriter.WriteDouble(((BsonDouble)this).Value);
  1194. break;
  1195. case BsonType.Int32:
  1196. bsonWriter.WriteInt32(((BsonInt32)this).Value);
  1197. break;
  1198. case BsonType.Int64:
  1199. bsonWriter.WriteInt64(((BsonInt64)this).Value);
  1200. break;
  1201. case BsonType.JavaScript:
  1202. bsonWriter.WriteJavaScript(((BsonJavaScript)this).Code);
  1203. break;
  1204. case BsonType.JavaScriptWithScope:
  1205. var script = (BsonJavaScriptWithScope)this;
  1206. bsonWriter.WriteJavaScriptWithScope(script.Code);
  1207. script.Scope.WriteTo(bsonWriter);
  1208. break;
  1209. case BsonType.MaxKey:
  1210. bsonWriter.WriteMaxKey();
  1211. break;
  1212. case BsonType.MinKey:
  1213. bsonWriter.WriteMinKey();
  1214. break;
  1215. case BsonType.Null:
  1216. bsonWriter.WriteNull();
  1217. break;
  1218. case BsonType.ObjectId:
  1219. var objectId = ((BsonObjectId)this).Value;
  1220. bsonWriter.WriteObjectId(objectId.Timestamp, objectId.Machine, objectId.Pid, objectId.Increment);
  1221. break;
  1222. case BsonType.RegularExpression:
  1223. BsonRegularExpression regex = (BsonRegularExpression)this;
  1224. bsonWriter.WriteRegularExpression(regex.Pattern, regex.Options);
  1225. break;
  1226. case BsonType.String:
  1227. bsonWriter.WriteString(((BsonString)this).Value);
  1228. break;
  1229. case BsonType.Symbol:
  1230. bsonWriter.WriteSymbol(((BsonSymbol)this).Name);
  1231. break;
  1232. case BsonType.Timestamp:
  1233. bsonWriter.WriteTimestamp(((BsonTimestamp)this).Value);
  1234. break;
  1235. case BsonType.Undefined:
  1236. bsonWriter.WriteUndefined();
  1237. break;
  1238. }
  1239. }
  1240. // protected methods
  1241. /// <summary>
  1242. /// Implementation of operator ==.
  1243. /// </summary>
  1244. /// <param name="rhs">The other BsonValue.</param>
  1245. /// <returns>True if the two BsonValues are equal according to ==.</returns>
  1246. protected virtual bool OperatorEqualsImplementation(BsonValue rhs)
  1247. {
  1248. return Equals(rhs); // default implementation of == is to call Equals
  1249. }
  1250. // explicit IConvertible implementation
  1251. TypeCode IConvertible.GetTypeCode()
  1252. {
  1253. switch (_bsonType)
  1254. {
  1255. case BsonType.Boolean: return TypeCode.Boolean;
  1256. case BsonType.DateTime: return TypeCode.DateTime;
  1257. case BsonType.Double: return TypeCode.Double;
  1258. case BsonType.Int32: return TypeCode.Int32;
  1259. case BsonType.Int64: return TypeCode.Int64;
  1260. case BsonType.String: return TypeCode.String;
  1261. default: return TypeCode.Object;
  1262. }
  1263. }
  1264. bool IConvertible.ToBoolean(IFormatProvider provider)
  1265. {
  1266. switch (_bsonType)
  1267. {
  1268. case BsonType.Boolean: return this.AsBoolean;
  1269. case BsonType.Double: return Convert.ToBoolean(this.AsDouble, provider);
  1270. case BsonType.Int32: return Convert.ToBoolean(this.AsInt32, provider);
  1271. case BsonType.Int64: return Convert.ToBoolean(this.AsInt64, provider);
  1272. case BsonType.String: return Convert.ToBoolean(this.AsString, provider);
  1273. default: throw new InvalidCastException();
  1274. }
  1275. }
  1276. byte IConvertible.ToByte(IFormatProvider provider)
  1277. {
  1278. switch (_bsonType)
  1279. {
  1280. case BsonType.Boolean: return Convert.ToByte(this.AsBoolean, provider);
  1281. case BsonType.Double: return Convert.ToByte(this.AsDouble, provider);
  1282. case BsonType.Int32: return Convert.ToByte(this.AsInt32, provider);
  1283. case BsonType.Int64: return Convert.ToByte(this.AsInt64, provider);
  1284. case BsonType.String: return Convert.ToByte(this.AsString, provider);
  1285. default: throw new InvalidCastException();
  1286. }
  1287. }
  1288. char IConvertible.ToChar(IFormatProvider provider)
  1289. {
  1290. switch (_bsonType)
  1291. {
  1292. case BsonType.Int32: return Convert.ToChar(this.AsInt32, provider);
  1293. case BsonType.Int64: return Convert.ToChar(this.AsInt64, provider);
  1294. case BsonType.String: return Convert.ToChar(this.AsString, provider);
  1295. default: throw new InvalidCastException();
  1296. }
  1297. }
  1298. DateTime IConvertible.ToDateTime(IFormatProvider provider)
  1299. {
  1300. switch (_bsonType)
  1301. {
  1302. case BsonType.DateTime: return this.AsDateTime;
  1303. case BsonType.String: return Convert.ToDateTime(this.AsString, provider);
  1304. default: throw new InvalidCastException();
  1305. }
  1306. }
  1307. decimal IConvertible.ToDecimal(IFormatProvider provider)
  1308. {
  1309. switch (_bsonType)
  1310. {
  1311. case BsonType.Boolean: return Convert.ToDecimal(this.AsBoolean, provider);
  1312. case BsonType.Double: return Convert.ToDecimal(this.AsDouble, provider);
  1313. case BsonType.Int32: return Convert.ToDecimal(this.AsInt32, provider);
  1314. case BsonType.Int64: return Convert.ToDecimal(this.AsInt64, provider);
  1315. case BsonType.String: return Convert.ToDecimal(this.AsString, provider);
  1316. default: throw new InvalidCastException();
  1317. }
  1318. }
  1319. double IConvertible.ToDouble(IFormatProvider provider)
  1320. {
  1321. switch (_bsonType)
  1322. {
  1323. case BsonType.Boolean: return Convert.ToDouble(this.AsBoolean, provider);
  1324. case BsonType.Double: return this.AsDouble;
  1325. case BsonType.Int32: return Convert.ToDouble(this.AsInt32, provider);
  1326. case BsonType.Int64: return Convert.ToDouble(this.AsInt64, provider);
  1327. case BsonType.String: return Convert.ToDouble(this.AsString, provider);
  1328. default: throw new InvalidCastException();
  1329. }
  1330. }
  1331. short IConvertible.ToInt16(IFormatProvider provider)
  1332. {
  1333. switch (_bsonType)
  1334. {
  1335. case BsonType.Boolean: return Convert.ToInt16(this.AsBoolean, provider);
  1336. case BsonType.Double: return Convert.ToInt16(this.AsDouble, provider);
  1337. case BsonType.Int32: return Convert.ToInt16(this.AsInt32, provider);
  1338. case BsonType.Int64: return Convert.ToInt16(this.AsInt64, provider);
  1339. case BsonType.String: return Convert.ToInt16(this.AsString, provider);
  1340. default: throw new InvalidCastException();
  1341. }
  1342. }
  1343. int IConvertible.ToInt32(IFormatProvider provider)
  1344. {
  1345. switch (_bsonType)
  1346. {
  1347. case BsonType.Boolean: return Convert.ToInt32(this.AsBoolean, provider);
  1348. case BsonType.Double: return Convert.ToInt32(this.AsDouble, provider);
  1349. case BsonType.Int32: return this.AsInt32;
  1350. case BsonType.Int64: return Convert.ToInt32(this.AsInt64, provider);
  1351. case BsonType.String: return Convert.ToInt32(this.AsString, provider);
  1352. default: throw new InvalidCastException();
  1353. }
  1354. }
  1355. long IConvertible.ToInt64(IFormatProvider provider)
  1356. {
  1357. switch (_bsonType)
  1358. {
  1359. case BsonType.Boolean: return Convert.ToInt64(this.AsBoolean, provider);
  1360. case BsonType.Double: return Convert.ToInt64(this.AsDouble, provider);
  1361. case BsonType.Int32: return Convert.ToInt64(this.AsInt32, provider);
  1362. case BsonType.Int64: return this.AsInt64;
  1363. case BsonType.String: return Convert.ToInt64(this.AsString, provider);
  1364. default: throw new InvalidCastException();
  1365. }
  1366. }
  1367. sbyte IConvertible.ToSByte(IFormatProvider provider)
  1368. {
  1369. switch (_bsonType)
  1370. {
  1371. case BsonType.Boolean: return Convert.ToSByte(this.AsBoolean, provider);
  1372. case BsonType.Double: return Convert.ToSByte(this.AsDouble, provider);
  1373. case BsonType.Int32: return Convert.ToSByte(this.AsInt32, provider);
  1374. case BsonType.Int64: return Convert.ToSByte(this.AsInt64, provider);
  1375. case BsonType.String: return Convert.ToSByte(this.AsString, provider);
  1376. default: throw new InvalidCastException();
  1377. }
  1378. }
  1379. float IConvertible.ToSingle(IFormatProvider provider)
  1380. {
  1381. switch (_bsonType)
  1382. {
  1383. case BsonType.Boolean: return Convert.ToSingle(this.AsBoolean, provider);
  1384. case BsonType.Double: return Convert.ToSingle(this.AsDouble, provider);
  1385. case BsonType.Int32: return Convert.ToSingle(this.AsInt32, provider);
  1386. case BsonType.Int64: return Convert.ToSingle(this.AsInt64, provider);
  1387. case BsonType.String: return Convert.ToSingle(this.AsString, provider);
  1388. default: throw new InvalidCastException();
  1389. }
  1390. }
  1391. string IConvertible.ToString(IFormatProvider provider)
  1392. {
  1393. switch (_bsonType)
  1394. {
  1395. case BsonType.Boolean: return Convert.ToString(this.AsBoolean, provider);
  1396. case BsonType.Double: return Convert.ToString(this.AsDouble, provider);
  1397. case BsonType.Int32: return Convert.ToString(this.AsInt32, provider);
  1398. case BsonType.Int64: return Convert.ToString(this.AsInt64, provider);
  1399. case BsonType.ObjectId: return this.AsObjectId.ToString();
  1400. case BsonType.String: return this.AsString;
  1401. default: throw new InvalidCastException();
  1402. }
  1403. }
  1404. object IConvertible.ToType(Type conversionType, IFormatProvider provider)
  1405. {
  1406. switch (_bsonType)
  1407. {
  1408. case BsonType.Boolean: return Convert.ChangeType(this.AsBoolean, conversionType, provider);
  1409. case BsonType.DateTime: return Convert.ChangeType(this.AsDateTime, conversionType, provider);
  1410. case BsonType.Double: return Convert.ChangeType(this.AsDouble, conversionType, provider);
  1411. case BsonType.Int32: return Convert.ChangeType(this.AsInt32, conversionType, provider);
  1412. case BsonType.Int64: return Convert.ChangeType(this.AsInt64, conversionType, provider);
  1413. case BsonType.ObjectId: return Convert.ChangeType(this.AsObjectId, conversionType, provider);
  1414. case BsonType.String: return Convert.ChangeType(this.AsString, conversionType, provider);
  1415. default: throw new InvalidCastException();
  1416. }
  1417. }
  1418. ushort IConvertible.ToUInt16(IFormatProvider provider)
  1419. {
  1420. switch (_bsonType)
  1421. {
  1422. case BsonType.Boolean: return Convert.ToUInt16(this.AsBoolean, provider);
  1423. case BsonType.Double: return Convert.ToUInt16(this.AsDouble, provider);
  1424. case BsonType.Int32: return Convert.ToUInt16(this.AsInt32, provider);
  1425. case BsonType.Int64: return Convert.ToUInt16(this.AsInt64, provider);
  1426. case BsonType.String: return Convert.ToUInt16(this.AsString, provider);
  1427. default: throw new InvalidCastException();
  1428. }
  1429. }
  1430. uint IConvertible.ToUInt32(IFormatProvider provider)
  1431. {
  1432. switch (_bsonType)
  1433. {
  1434. case BsonType.Boolean: return Convert.ToUInt32(this.AsBoolean, provider);
  1435. case BsonType.Double: return Convert.ToUInt32(this.AsDouble, provider);
  1436. case BsonType.Int32: return Convert.ToUInt16(this.AsInt32, provider);
  1437. case BsonType.Int64: return Convert.ToUInt32(this.AsInt64, provider);
  1438. case BsonType.String: return Convert.ToUInt32(this.AsString, provider);
  1439. default: throw new InvalidCastException();
  1440. }
  1441. }
  1442. ulong IConvertible.ToUInt64(IFormatProvider provider)
  1443. {
  1444. switch (_bsonType)
  1445. {
  1446. case BsonType.Boolean: return Convert.ToUInt64(this.AsBoolean, provider);
  1447. case BsonType.Double: return Convert.ToUInt64(this.AsDouble, provider);
  1448. case BsonType.Int32: return Convert.ToUInt64(this.AsInt32, provider);
  1449. case BsonType.Int64: return Convert.ToUInt16(this.AsInt64, provider);
  1450. case BsonType.String: return Convert.ToUInt64(this.AsString, provider);
  1451. default: throw new InvalidCastException();
  1452. }
  1453. }
  1454. }
  1455. }