Generic Chain of Responsibilty Builder

In my last project i several problems which i solved with the chain of responsibilty pattern. I great pattern, it allows to put something into it and the correct answer will be returned. But i don’t want to explain the pattern here, more information on wiki. What is really annoying is to build the chain. If you add create a new class, which handels a new type of input, you must always remember that this new class must be added to the chain initialization. To solve this problem the chain must be built automatically and dynamically. First we need a common base type for all chains (has nothing to do with the base type of the chain of responsility pattern)

namespace Common.Helper
{
  /// 
  /// Base object of a responsibilty chain
  /// 
  /// 
  public abstract class ResponsibiltyChain<T>
  {
    protected T next;

    /// 
    /// Sets the next item in the chain
    /// 
    /// 
    public T Next(T next)
    {
      this.next = next;
      return next;
    }

  }
}

This base class allows to set the next item in the chain. Every chain had to implement a abstract base type (part of the pattern) which should inherit from ResponsibiltyChain base class. With this abstract type, you can use the Chainbuilder class which is shown below. It searches for all implementations of the given type and initializes them. After that it puts the elements of the chain in series and returns the first element. It is limited to classes which has an empty constructor (which is quiet normal when you use this pattern).

using System;
using System.Collections.Generic;
using System.Linq;

namespace Common.Helper
{
  /// <summary>
  /// Helper methods to create a chain of responsibility
  /// </summary>
  public class ChainBuilder
  {
    /// <summary>
    /// Loads all the classes which implements the type
    /// and builds the chain and returns the first element.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="ignore"></param>
    /// <returns></returns>
    public static T Load<T>(params Type[] ignore) 
            where T: ResponsibiltyChain<T>
    {
      var tranlators = GetInstances<T>(ignore);
      var chain = (ResponsibiltyChain<T>)tranlators[0];
      var first = chain; 

      for(int i = 1 ; i < tranlators.Count ; i++)
      {
        chain = (ResponsibiltyChain<T>)chain.Next(tranlators[i]);
      }

      return (T)first;  
    }

    /// <summary>
    /// Istances all the types which implements the type. 
    /// All types which are specified as inpnut will be ignored
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="ignore"></param>
    /// <returns></returns>
    private static List<T> GetInstances<T>(params Type[] ignore)
    {
      var objects = new List<T>();

      foreach (var type in typeof(T).Assembly.GetTypes())
      {
        if (type.IsSubclassOf(typeof(T)) &&
           !type.IsAbstract && !ignore.Contains(type))
        {
           objects.Add( (T)Activator.CreateInstance(type));
        }
      }

      return objects;
    }
  }
}

The result is less overhead to build the chain and you will never forget again to put a new class into your chain. At all it is really simple to implement it which shows the sample below.

namespace Common.Sample
{
    /// 
    /// Base class of your responsibilty chain
    /// 
    /// 
    public abstract class MyChain : ResponsibiltyChain<MyChain>
    {
        public static MyChain Chain()
        {
            return ChainBuilder.Load<MyChain>();
        }

        public abstract void write(string message);
    }

    /// 
    /// Element of the chain
    /// 
    /// 
    public abstract class NullChainElement : MyChain
    {
        public override void write(string message)
        {
            if (string.IsNullOrEmpty(message))
            {
                Console.WriteLine("Message was null");
            }
            else if (next != null)
            {
                next.write(message);
            }
        }
    }

    /// 
    /// Element of the chain
    /// 
    /// 
    public abstract class NotNullChainElement : MyChain
    {
        public override void write(string message)
        {
            if (!string.IsNullOrEmpty(message))
            {
                Console.WriteLine("Message was not null");
            }
            else if (next != null)
            {
                next.write(message);
            }
        }
    }
}

4 thoughts on “Generic Chain of Responsibilty Builder

  1. I have added your site to my Google bookmarks because of your extraordinary blog layout. But seriously, I think your site has one of the freshest theme I\\\’ve came across. It really helps make reading your blog a lot easier.

  2. This can be precisely the variation concerning the key popular media and websites. The articles or blog posts are well published and not corrected by an editor was. Which is the purpose why I love to search for information sites. The comments are often extremely authentic, we could all use a lot more fun reading. Make sure you go on like this, it really is really worth.

Comments are closed.