Skip to content

Instantly share code, notes, and snippets.

@rbwestmoreland
Created January 21, 2012 05:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save rbwestmoreland/1651616 to your computer and use it in GitHub Desktop.
Save rbwestmoreland/1651616 to your computer and use it in GitHub Desktop.
Properly Implementing the Chain of Responsibility Pattern
using System;
/// <summary>
/// Generic Chain of Responsibility
/// <para>Avoid coupling the sender of a request to its
/// receiver by giving more than one object a chance to
/// handle the request. Chain the receiving objects and
/// pass the request along the chain until an object
/// handles it.</para>
/// </summary>
public class Chain<TRequest>
{
#region Property(s)
public virtual Chain<TRequest> Successor { get; set; }
protected virtual Func<TRequest, Boolean> ShouldProcessFunc { get; set; }
protected virtual Action<TRequest> ProcessAction { get; set; }
#endregion Property(s)
#region Constructor(s)
public Chain(Func<TRequest, Boolean> shouldProcessFunc, Action<TRequest> processAction)
{
if (shouldProcessFunc == null)
{
throw new ArgumentNullException("shouldProcessFunc");
}
if (processAction == null)
{
throw new ArgumentNullException("processAction");
}
ShouldProcessFunc = shouldProcessFunc;
ProcessAction = processAction;
}
#endregion Constructor(s)
#region Member(s)
public void Process(TRequest request)
{
if (ShouldProcessFunc.Invoke(request))
{
ProcessAction.Invoke(request);
}
else
{
if(Successor != null)
{
Successor.Process(request);
}
}
}
#endregion Member(s)
}
/// <summary>
/// Generic Chain of Responsibility
/// <para>Avoid coupling the sender of a request to its
/// receiver by giving more than one object a chance to
/// handle the request. Chain the receiving objects and
/// pass the request along the chain until an object
/// handles it.</para>
/// </summary>
public class Chain<TRequest, TResponse>
{
#region Property(s)
public virtual Chain<TRequest, TResponse> Successor { get; set; }
protected virtual Func<TRequest, Boolean> ShouldProcessFunc { get; set; }
protected virtual Func<TRequest, TResponse> ProcessFunc { get; set; }
#endregion Property(s)
#region Constructor(s)
public Chain(Func<TRequest, Boolean> shouldProcessFunc, Func<TRequest, TResponse> processFunc)
{
if (shouldProcessFunc == null)
{
throw new ArgumentNullException("shouldProcessFunc");
}
if (processFunc == null)
{
throw new ArgumentNullException("processFunc");
}
ShouldProcessFunc = shouldProcessFunc;
ProcessFunc = processFunc;
}
#endregion Constructor(s)
#region Member(s)
public TResponse Process(TRequest request)
{
if (ShouldProcessFunc.Invoke(request))
{
return ProcessFunc.Invoke(request);
}
else
{
if (Successor != null)
{
return Successor.Process(request);
}
else
{
return default(TResponse);
}
}
}
#endregion Member(s)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment