title: Composite Design pattern & common descendant methods
body: <p>I am using a composite pattern as shown in the class diagram below. Basically my primary leaf (an Allocation) has a single property, Duration, that I want to accumulate in various composites.</p>
  
  <p>I also want to have a count of allocations, and the ability to return the allocations as a collection I can use for data binding in presentations.</p>
  
  <p>This question is about the C# implementation, specifically:</p>
  
  <ol>
  <li>There is an interesting <a href="https://stackoverflow.com/questions/5262201/how-to-use-linq-to-select-all-descendants-of-a-composite-object">post here</a> that has an extension to do this recursively, as well as an alternative approach that avoids recursion altogether. Would you have a common method to get at the Allocations the way I am doing? I haven't decided yet if the code I wrote feels awkward because I am not comfortable with pattern, or if it <em>is</em> awkward!</li>
  <li>Do you see any easy opportunities here to cache the results of the first iteration and thereby minimize further iteration?</li>
  </ol>
  
  <p>Cheers,<br>
  Berryl</p>
  
  <p><img src="https://i.stack.imgur.com/dtXwV.png" alt="this class diagram"></p>
  
  <h1>Code in the Composite class</h1>
  
  <pre><code>public class AllocationComposite : AllocationNode
  {
      protected readonly IList&lt;AllocationNode&gt; _children;
      public AllocationComposite() { _children = new List&lt;AllocationNode&gt;(); }
  
      #region Implementation of AllocationNode
  
      public override void Adopt(AllocationNode node) ...
      public override void Adopt(IEnumerable&lt;AllocationNode&gt; nodes)...
      public override void Orphan(AllocationNode node)...
      public override void Orphan(IEnumerable&lt;AllocationNode&gt; nodes)...
  
      public override IEnumerable&lt;AllocationNode&gt; Descendants
      {
          get
          {
              return _children.Concat(_children.SelectMany(child =&gt; child.Descendants));
          }
      }
  
      public override IEnumerable&lt;Allocation&gt; Allocations
      {
          get
          {
              return Descendants.OfType&lt;Allocation&gt;();
          }
      }
  
      public override TimeSpan Duration {
          get {
              return Allocations.Aggregate(TimeSpan.Zero, (current, child) =&gt; current + child.Duration);
           }
      }
  
      public override int Count { get { return Allocations.Count(); } }
  
      #endregion
  
      public override string ToString() {
          return String.Format("{0} for {1}", 
              "allocation".PluralizeWithCount(Count), 
              "hour".PluralizeWithCount(Duration.TotalHours, "F2"));
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <h1>Default implementation in abstract Component</h1>
  
  <pre><code>public abstract class AllocationNode: Entity, IAllocationNode
  {
      #region Implementation of AllocationNode
  
      public virtual TimeSpan Duration { get { return TimeSpan.Zero; } set {  } }
  
      public virtual void Adopt(AllocationNode node) { throw new InvalidOperationException(...)); }
      public virtual void Adopt(IEnumerable&lt;AllocationNode&gt; nodes) { throw new InvalidOperationException(...)); }
      public virtual void Orphan(AllocationNode node) { throw new InvalidOperationException(...)); }
      public virtual void Orphan(IEnumerable&lt;AllocationNode&gt; nodes) { throw new InvalidOperationException(...)); }
  
      public virtual int Count { get { return 1; } }
  
      public virtual IEnumerable&lt;AllocationNode&gt; Descendants { get { return Enumerable.Empty&lt;AllocationNode&gt;(); } }
  
      public virtual IEnumerable&lt;Allocation&gt; Allocations { get { return Enumerable.Empty&lt;Allocation&gt;(); } }
  
      #endregion
  }
  </code></pre>