/* Copyright 2010-present MongoDB Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.IO; using MongoDB.Bson.IO; using MongoDB.Bson.Serialization; using MongoDB.Bson.Serialization.Attributes; using MongoDB.Bson.Serialization.Serializers; namespace MongoDB.Bson { /// /// Represents a BSON array that is not materialized until you start using it. /// [BsonSerializer(typeof(MaterializedOnDemandBsonArraySerializer))] public abstract class MaterializedOnDemandBsonArray : BsonArray, IDisposable { // private fields private bool _disposed; private bool _isMaterialized; // constructors /// /// Initializes a new instance of the class. /// protected MaterializedOnDemandBsonArray() { } // public properties /// /// Gets or sets the total number of elements the internal data structure can hold without resizing. /// public override int Capacity { get { EnsureIsMaterialized(); return base.Capacity; } set { EnsureIsMaterialized(); base.Capacity = value; } } /// /// Gets the count of array elements. /// public override int Count { get { EnsureIsMaterialized(); return base.Count; } } /// /// Gets a value indicating whether this instance is disposed. /// /// /// true if this instance is disposed; otherwise, false. /// public bool IsDisposed { get { return _disposed; } } /// /// Gets a value indicating whether this instance is materialized. /// /// /// true if this instance is materialized; otherwise, false. /// public bool IsMaterialized { get { return _isMaterialized; } } /// /// Gets the array elements as raw values (see BsonValue.RawValue). /// [Obsolete("Use ToArray to ToList instead.")] public override IEnumerable RawValues { get { EnsureIsMaterialized(); return base.RawValues; } } /// /// Gets the array elements. /// public override IEnumerable Values { get { EnsureIsMaterialized(); return base.Values; } } // public indexers /// /// Gets or sets a value by position. /// /// The position. /// The value. public override BsonValue this[int index] { get { EnsureIsMaterialized(); return base[index]; } set { EnsureIsMaterialized(); base[index] = value; } } // public methods /// /// Adds an element to the array. /// /// The value to add to the array. /// The array (so method calls can be chained). public override BsonArray Add(BsonValue value) { EnsureIsMaterialized(); return base.Add(value); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Adds multiple elements to the array. /// /// A list of values to add to the array. /// The array (so method calls can be chained). public override BsonArray AddRange(IEnumerable values) { EnsureIsMaterialized(); return base.AddRange(values); } /// /// Clears the array. /// public override void Clear() { EnsureIsMaterialized(); base.Clear(); } /// /// Creates a shallow clone of the array (see also DeepClone). /// /// /// A shallow clone of the array. /// public override BsonValue Clone() { EnsureIsMaterialized(); return base.Clone(); } /// /// Compares the array to another array. /// /// The other array. /// A 32-bit signed integer that indicates whether this array is less than, equal to, or greather than the other. public override int CompareTo(BsonArray other) { EnsureIsMaterialized(); return base.CompareTo(other); } /// /// Compares the array to another BsonValue. /// /// The other BsonValue. /// A 32-bit signed integer that indicates whether this array is less than, equal to, or greather than the other BsonValue. public override int CompareTo(BsonValue other) { EnsureIsMaterialized(); return base.CompareTo(other); } /// /// Tests whether the array contains a value. /// /// The value to test for. /// True if the array contains the value. public override bool Contains(BsonValue value) { EnsureIsMaterialized(); return base.Contains(value); } /// /// Copies elements from this array to another array. /// /// The other array. /// The zero based index of the other array at which to start copying. public override void CopyTo(BsonValue[] array, int arrayIndex) { EnsureIsMaterialized(); base.CopyTo(array, arrayIndex); } /// /// Copies elements from this array to another array as raw values (see BsonValue.RawValue). /// /// The other array. /// The zero based index of the other array at which to start copying. [Obsolete("Use ToArray or ToList instead.")] public override void CopyTo(object[] array, int arrayIndex) { EnsureIsMaterialized(); base.CopyTo(array, arrayIndex); } /// /// Creates a deep clone of the array (see also Clone). /// /// /// A deep clone of the array. /// public override BsonValue DeepClone() { EnsureIsMaterialized(); return base.DeepClone(); } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } /// /// Determines whether the specified , is equal to this instance. /// /// The to compare with this instance. /// /// true if the specified is equal to this instance; otherwise, false. /// public override bool Equals(object obj) { EnsureIsMaterialized(); return base.Equals(obj); } /// /// Gets an enumerator that can enumerate the elements of the array. /// /// An enumerator. public override IEnumerator GetEnumerator() { EnsureIsMaterialized(); return base.GetEnumerator(); } /// /// Gets the hash code. /// /// The hash code. public override int GetHashCode() { EnsureIsMaterialized(); return base.GetHashCode(); } /// /// Gets the index of a value in the array. /// /// The value to search for. /// The zero based index of the value (or -1 if not found). public override int IndexOf(BsonValue value) { EnsureIsMaterialized(); return base.IndexOf(value); } /// /// Gets the index of a value in the array. /// /// The value to search for. /// The zero based index at which to start the search. /// The zero based index of the value (or -1 if not found). public override int IndexOf(BsonValue value, int index) { EnsureIsMaterialized(); return base.IndexOf(value, index); } /// /// Gets the index of a value in the array. /// /// The value to search for. /// The zero based index at which to start the search. /// The number of elements to search. /// The zero based index of the value (or -1 if not found). public override int IndexOf(BsonValue value, int index, int count) { EnsureIsMaterialized(); return base.IndexOf(value, index, count); } /// /// Inserts a new value into the array. /// /// The zero based index at which to insert the new value. /// The new value. public override void Insert(int index, BsonValue value) { EnsureIsMaterialized(); base.Insert(index, value); } /// /// Removes the first occurrence of a value from the array. /// /// The value to remove. /// True if the value was removed. public override bool Remove(BsonValue value) { EnsureIsMaterialized(); return base.Remove(value); } /// /// Removes an element from the array. /// /// The zero based index of the element to remove. public override void RemoveAt(int index) { EnsureIsMaterialized(); base.RemoveAt(index); } /// /// Converts the BsonArray to an array of BsonValues. /// /// An array of BsonValues. public override BsonValue[] ToArray() { EnsureIsMaterialized(); return base.ToArray(); } /// /// Converts the BsonArray to a list of BsonValues. /// /// A list of BsonValues. public override List ToList() { EnsureIsMaterialized(); return base.ToList(); } /// /// Returns a string representation of the array. /// /// A string representation of the array. public override string ToString() { EnsureIsMaterialized(); return base.ToString(); } // protected methods /// /// Releases unmanaged and - optionally - managed resources. /// /// true to release both managed and unmanaged resources; false to release only unmanaged resources. protected virtual void Dispose(bool disposing) { _disposed = true; } /// /// Materializes the BsonArray. /// /// The materialized elements. protected abstract IEnumerable Materialize(); /// /// Informs subclasses that the Materialize process completed so they can free any resources related to the unmaterialized state. /// protected abstract void MaterializeCompleted(); /// /// Throws if disposed. /// /// protected void ThrowIfDisposed() { if (_disposed) { throw new ObjectDisposedException(GetType().Name); } } // private methods private void EnsureIsMaterialized() { ThrowIfDisposed(); if (!_isMaterialized) { var values = Materialize(); try { _isMaterialized = true; base.AddRange(values); MaterializeCompleted(); } catch { base.Clear(); _isMaterialized = false; throw; } } } internal class MaterializedOnDemandBsonArraySerializer : AbstractClassSerializer { } } }