main
 1namespace utility
 2{
 3  using System;
 4  using System.Collections.Generic;
 5
 6  public interface IVisitor<T>
 7  {
 8    void Visit(T item);
 9  }
10
11  public interface IVisitable<T>
12  {
13    void Accept(IVisitor<T> visitor);
14  }
15
16  public interface IValueReturningVisitor<T, TResult> : IVisitor<T>
17  {
18    TResult Result();
19  }
20
21  public static class Visiting
22  {
23    public static TResult AcceptAndReturnResultFrom<T, TResult>(this IVisitable<T> visitable, IValueReturningVisitor<T, TResult> visitor)
24    {
25      visitable.Accept(visitor);
26      return visitor.Result();
27    }
28
29    public static IEnumerable<T> Collect<T>( this IVisitable<T> visitable, Func<T, bool> predicate)
30    {
31      return new Collectable<T>(predicate).CollectFrom(visitable);
32    }
33  }
34
35  public interface ICollectable<T>
36  {
37    IEnumerable<T> CollectFrom(IVisitable<T> visitable);
38  }
39
40  public class Collectable<T> : ICollectable<T>
41  {
42    Func<T, bool> predicate;
43
44    public Collectable(Func<T, bool> predicate) 
45    {
46      this.predicate = predicate;
47    }
48
49    public IEnumerable<T> CollectFrom(IVisitable<T> visitable)
50    {
51      var results = new List<T>();
52      visitable.Accept(new AnonymousVisitor<T>(item =>
53      {
54        if(predicate(item)) results.Add(item);
55      }));
56      return results;
57    }
58  }
59
60  public class AnonymousVisitor<T> : IVisitor<T>
61  {
62    Action<T> visitor;
63
64    public AnonymousVisitor(Action<T> visitor) 
65    {
66      this.visitor = visitor;
67    }
68
69    public void Visit(T item)
70    {
71      visitor(item);
72    }
73  }
74}