The Labs \ Source Viewer \ SSCLI \ System.Xml.XPath \ Enumerator

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XPathNodeIterator.cs" company="Microsoft">
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. // </copyright>
  14. //------------------------------------------------------------------------------
  15. namespace System.Xml.XPath
  16. {
  17.     using System;
  18.     using System.Collections;
  19.     using System.Diagnostics;
  20.     using System.Text;
  21.    
  22.     [DebuggerDisplay("Position={CurrentPosition}, Current={Current == null ? null : (object) new XPathNavigator.DebuggerDisplayProxy(Current)}")]
  23.     public abstract class XPathNodeIterator : ICloneable, IEnumerable
  24.     {
  25.         internal int count = -1;
  26.        
  27.         object ICloneable.Clone()
  28.         {
  29.             return this.Clone();
  30.         }
  31.        
  32.         public abstract XPathNodeIterator Clone();
  33.         public abstract bool MoveNext();
  34.         public abstract XPathNavigator Current {
  35.             get;
  36.         }
  37.         public abstract int CurrentPosition {
  38.             get;
  39.         }
  40.         public virtual int Count {
  41.             get {
  42.                 if (count == -1) {
  43.                     XPathNodeIterator clone = this.Clone();
  44.                     while (clone.MoveNext())
  45.                         ;
  46.                     count = clone.CurrentPosition;
  47.                 }
  48.                 return count;
  49.             }
  50.         }
  51.         public virtual IEnumerator GetEnumerator()
  52.         {
  53.             return new Enumerator(this);
  54.         }
  55.        
  56.         /// <summary>
  57.         /// Implementation of a resetable enumerator that is linked to the XPathNodeIterator used to create it.
  58.         /// </summary>
  59.         private class Enumerator : IEnumerator
  60.         {
  61.             private XPathNodeIterator original;
  62.             // Keep original XPathNodeIterator in case Reset() is called
  63.             private XPathNodeIterator current;
  64.             private bool iterationStarted;
  65.            
  66.             public Enumerator(XPathNodeIterator original)
  67.             {
  68.                 this.original = original.Clone();
  69.             }
  70.            
  71.             public virtual object Current {
  72.                 get {
  73.                     // 1. Do not reuse the XPathNavigator, as we do in XPathNodeIterator
  74.                     // 2. Throw exception if current position is before first node or after the last node
  75.                     if (this.iterationStarted) {
  76.                         // Current is null if iterator is positioned after the last node
  77.                         if (this.current == null)
  78.                             throw new InvalidOperationException(Res.GetString(Res.Sch_EnumFinished, string.Empty));
  79.                        
  80.                         return this.current.Current.Clone();
  81.                     }
  82.                    
  83.                     // User must call MoveNext before accessing Current property
  84.                     throw new InvalidOperationException(Res.GetString(Res.Sch_EnumNotStarted, string.Empty));
  85.                 }
  86.             }
  87.            
  88.             public virtual bool MoveNext()
  89.             {
  90.                 // Delegate to XPathNodeIterator
  91.                 if (!this.iterationStarted) {
  92.                     // Reset iteration to original position
  93.                     this.current = this.original.Clone();
  94.                     this.iterationStarted = true;
  95.                 }
  96.                
  97.                 if (this.current == null || !this.current.MoveNext()) {
  98.                     // Iteration complete
  99.                     this.current = null;
  100.                     return false;
  101.                 }
  102.                 return true;
  103.             }
  104.            
  105.             public virtual void Reset()
  106.             {
  107.                 this.iterationStarted = false;
  108.             }
  109.         }
  110.     }
  111. }

Developer Fusion