PageRenderTime 505ms CodeModel.GetById 241ms app.highlight 5ms RepoModel.GetById 257ms app.codeStats 0ms

/Rhino.Etl.Core/Enumerables/CachingEnumerable.cs

http://github.com/ayende/rhino-etl
C# | 132 lines | 60 code | 10 blank | 62 comment | 6 complexity | 18b1d03bc0b8117f86e80ffa11c93212 MD5 | raw file
  1namespace Rhino.Etl.Core.Enumerables
  2{
  3    using System.Collections;
  4    using System.Collections.Generic;
  5
  6    /// <summary>
  7    /// There are several places where we need to iterate over an enumerable
  8    /// several times, but we cannot assume that it is safe to do so.
  9    /// This class will allow to safely use an enumerable multiple times, by caching
 10    /// the results after the first iteration.
 11    /// </summary>
 12    /// <typeparam name="T"></typeparam>
 13    public class CachingEnumerable<T> : IEnumerable<T>, IEnumerator<T>
 14    {
 15        private bool? isFirstTime = null;
 16        private IEnumerator<T> internalEnumerator;
 17        private readonly LinkedList<T> cache = new LinkedList<T>();
 18
 19        /// <summary>
 20        /// Initializes a new instance of the <see cref="CachingEnumerable&lt;T&gt;"/> class.
 21        /// </summary>
 22        /// <param name="inner">The inner.</param>
 23        public CachingEnumerable(IEnumerable<T> inner)
 24        {
 25            internalEnumerator = inner.GetEnumerator();
 26        }
 27
 28        ///<summary>
 29        ///Returns an enumerator that iterates through the collection.
 30        ///</summary>
 31        ///
 32        ///<returns>
 33        ///A <see cref="T:System.Collections.Generic.IEnumerator`1"></see> that can be used to iterate through the collection.
 34        ///</returns>
 35        ///<filterpriority>1</filterpriority>
 36        IEnumerator<T> IEnumerable<T>.GetEnumerator()
 37        {
 38            if(isFirstTime==null)
 39            {
 40                isFirstTime = true;
 41            }
 42            else if(isFirstTime.Value)
 43            {
 44                isFirstTime = false;
 45                internalEnumerator.Dispose();
 46                internalEnumerator = cache.GetEnumerator();
 47            }
 48            else 
 49            {
 50                internalEnumerator = cache.GetEnumerator();
 51            }
 52
 53            return this;
 54        }
 55
 56        ///<summary>
 57        ///Returns an enumerator that iterates through a collection.
 58        ///</summary>
 59        ///
 60        ///<returns>
 61        ///An <see cref="T:System.Collections.IEnumerator"></see> object that can be used to iterate through the collection.
 62        ///</returns>
 63        ///<filterpriority>2</filterpriority>
 64        public IEnumerator GetEnumerator()
 65        {
 66            return ((IEnumerable<T>)this).GetEnumerator();
 67        }
 68
 69        ///<summary>
 70        ///Gets the element in the collection at the current position of the enumerator.
 71        ///</summary>
 72        ///
 73        ///<returns>
 74        ///The element in the collection at the current position of the enumerator.
 75        ///</returns>
 76        ///
 77        T IEnumerator<T>.Current
 78        {
 79            get { return internalEnumerator.Current; }
 80        }
 81
 82        ///<summary>
 83        ///Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
 84        ///</summary>
 85        ///<filterpriority>2</filterpriority>
 86        public void Dispose()
 87        {
 88            internalEnumerator.Dispose();
 89        }
 90
 91        ///<summary>
 92        ///Advances the enumerator to the next element of the collection.
 93        ///</summary>
 94        ///
 95        ///<returns>
 96        ///true if the enumerator was successfully advanced to the next element; false if the enumerator has passed the end of the collection.
 97        ///</returns>
 98        ///
 99        ///<exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception><filterpriority>2</filterpriority>
100        public bool MoveNext()
101        {
102            bool result = internalEnumerator.MoveNext();
103            if (result && isFirstTime.Value)
104                cache.AddLast(internalEnumerator.Current);
105            return result;
106        }
107
108        ///<summary>
109        ///Sets the enumerator to its initial position, which is before the first element in the collection.
110        ///</summary>
111        ///
112        ///<exception cref="T:System.InvalidOperationException">The collection was modified after the enumerator was created. </exception><filterpriority>2</filterpriority>
113        public void Reset()
114        {
115            internalEnumerator.Reset();
116        }
117
118        ///<summary>
119        ///Gets the current element in the collection.
120        ///</summary>
121        ///
122        ///<returns>
123        ///The current element in the collection.
124        ///</returns>
125        ///
126        ///<exception cref="T:System.InvalidOperationException">The enumerator is positioned before the first element of the collection or after the last element.-or- The collection was modified after the enumerator was created.</exception><filterpriority>2</filterpriority>
127        public object Current
128        {
129            get { return internalEnumerator.Current; }
130        }
131    }
132}