1 //------------------------------------------------------------------------------
2 // <copyright file="XPathNodeIterator.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 using System.Collections;
9 using System.Diagnostics;
12 namespace System.Xml.XPath {
14 [DebuggerDisplay("Position={CurrentPosition}, Current={debuggerDisplayProxy}")]
15 public abstract class XPathNodeIterator : ICloneable, IEnumerable {
16 internal int count = -1;
18 object ICloneable.Clone() { return this.Clone(); }
20 public abstract XPathNodeIterator Clone();
21 public abstract bool MoveNext();
22 public abstract XPathNavigator Current { get; }
23 public abstract int CurrentPosition { get; }
24 public virtual int Count {
27 XPathNodeIterator clone = this.Clone();
28 while(clone.MoveNext()) ;
29 count = clone.CurrentPosition;
34 public virtual IEnumerator GetEnumerator() {
35 return new Enumerator(this);
38 private object debuggerDisplayProxy { get { return Current == null ? null : (object)new XPathNavigator.DebuggerDisplayProxy(Current); } }
41 /// Implementation of a resetable enumerator that is linked to the XPathNodeIterator used to create it.
43 private class Enumerator : IEnumerator {
44 private XPathNodeIterator original; // Keep original XPathNodeIterator in case Reset() is called
45 private XPathNodeIterator current;
46 private bool iterationStarted;
48 public Enumerator(XPathNodeIterator original) {
49 this.original = original.Clone();
52 public virtual object Current {
54 // 1. Do not reuse the XPathNavigator, as we do in XPathNodeIterator
55 // 2. Throw exception if current position is before first node or after the last node
56 if (this.iterationStarted) {
57 // Current is null if iterator is positioned after the last node
58 if (this.current == null)
59 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumFinished, string.Empty));
61 return this.current.Current.Clone();
64 // User must call MoveNext before accessing Current property
65 throw new InvalidOperationException(Res.GetString(Res.Sch_EnumNotStarted, string.Empty));
69 public virtual bool MoveNext() {
70 // Delegate to XPathNodeIterator
71 if (!this.iterationStarted) {
72 // Reset iteration to original position
73 this.current = this.original.Clone();
74 this.iterationStarted = true;
77 if (this.current == null || !this.current.MoveNext()) {
85 public virtual void Reset() {
86 this.iterationStarted = false;
90 private struct DebuggerDisplayProxy {
91 private XPathNodeIterator nodeIterator;
93 public DebuggerDisplayProxy(XPathNodeIterator nodeIterator) {
94 this.nodeIterator = nodeIterator;
97 public override string ToString() {
98 // Position={CurrentPosition}, Current={Current == null ? null : (object) new XPathNavigator.DebuggerDisplayProxy(Current)}
99 StringBuilder sb = new StringBuilder();
100 sb.Append("Position=");
101 sb.Append(nodeIterator.CurrentPosition);
102 sb.Append(", Current=");
103 if (nodeIterator.Current == null) {
107 sb.Append(new XPathNavigator.DebuggerDisplayProxy(nodeIterator.Current).ToString());
110 return sb.ToString();