コンビネーションモード拡張、選択された再帰


1.選択インタフェースルールを定義する
 public interface IMatchRule

    {

        bool IsMatch(Component target);

    }
 public abstract class Component

    {

        /// <summary>

        ///  

        /// </summary>

        protected IList<Component> children;



        /// <summary>

        /// Leaf Composite . setter 

        /// </summary>

        public virtual string Name

        {

            get;

            set;

        }



        /// <summary>

        ///  Composite 

        /// </summary>

        /// <param name="child"></param>

        public virtual void Add(Component child) { children.Add(child); }

        public virtual void Remove(Component child) { children.Remove(child); }

        public virtual Component this[int index] { get { return children[index]; } }



        /// <summary>

        ///  : , 

        /// </summary>

        /// <returns></returns>

        public virtual IEnumerable<Component> Enumerate(IMatchRule rule)

        {

            if ((rule == null) || (rule.IsMatch(this)))

                yield return this;

            if ((children != null) && (children.Count > 0))

                foreach (Component child in children)

                    foreach (Component item in child.Enumerate(rule))

                        if ((rule == null) || (rule.IsMatch(item)))

                            yield return item;

        }

        public virtual IEnumerable<Component> Enumerate() { return Enumerate(null); }

    }
    public class Leaf : Component

    {

        /// <summary>

        ///  

        /// </summary>

        /// <param name="child"></param>

        public override void Add(Component child) { throw new NotSupportedException(); }

        public override void Remove(Component child) { throw new NotSupportedException(); }

        public override Component this[int index] { get { throw new NotSupportedException(); } }

    }
  public class Composite : Component

    {

        public Composite() { base.children = new List<Component>(); }

    }

工場クラス
 public class ComponentFactory

    {

        public Component Create<T>(string name) where T : Component, new()

        {

            return new T() { Name = name };

        }



        /// <summary>

        ///  (Fluent Method):  

        /// </summary>

        /// <typeparam name="T"></typeparam>

        /// <param name="parent"></param>

        /// <param name="name"></param>

        /// <returns></returns>

        public Component Create<T>(Component parent, string name)

            where T : Component, new()

        {

            if (parent == null) throw new ArgumentNullException("parent");

            if (!(parent is Composite)) throw new Exception("non-somposite type");

            Component instance = Create<T>(name);

            parent.Add(instance);

            return instance;

        }

    }

実装で呼び出すと
using System;

using System.Collections.Generic;

using System.Diagnostics;

using System.Linq;

using C = MarvellousWorks.PracticalPattern.Composite.Iterating;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace MarvellousWorks.PracticalPattern.Composite.Tests.Iterating

{

    [TestClass]

    public class CompositeFixture

    {

        #region non-linq version



        class LeafMatchRule : C.IMatchRule

        {

            public bool IsMatch(C.Component target)

            {

                if (target == null) return false;

                return target.GetType().IsAssignableFrom(typeof(C.Leaf));

            }

        }



        C.Component corporate;



        /// <summary>

        ///  

        /// </summary>

        [TestInitialize]

        public void Initialize()

        {

            var factory = new C.ComponentFactory();

            corporate = factory.Create<C.Composite>("corporate");           // 1

            factory.Create<C.Leaf>(corporate, "president");                 // 2

            factory.Create<C.Leaf>(corporate, "vice president");            // 3

            var sales = factory.Create<C.Composite>(corporate, "sales");    // 4

            var market = factory.Create<C.Composite>(corporate, "market");  // 5

            factory.Create<C.Leaf>(sales, "joe");                           // 6

            factory.Create<C.Leaf>(sales, "bob");                           // 7

            factory.Create<C.Leaf>(market, "judi");                         // 8

            var branch = factory.Create<C.Composite>(corporate, "branch");  // 9

            factory.Create<C.Leaf>(branch, "manager");                      // 10

            factory.Create<C.Leaf>(branch, "peter");                        // 11

        }



        [TestMethod]

        public void Test()

        {

            Assert.AreEqual<int>(7, corporate.Enumerate(new LeafMatchRule()).Count());

            Assert.AreEqual<int>(11, corporate.Enumerate().Count());



            //   leaf 

            Trace.WriteLine("List all leaves:
------------------------
"); foreach (var item in corporate.Enumerate(new LeafMatchRule())) Trace.WriteLine(item.Name ); } #endregion } }