I recently had reason to implement a simple chain of responsibility in order to simplify some logic. Rather than a large number of sequential if statements to implement a sequence of conditional exclusive actions I used this structure to simplify the logic.

The basis of the implementation is a field that is a collection of delegates. The delegate take parameters as needed to determine if an action is applicable and also to implement the action. It also returns bool. For example:

private static readonly ICollection<Func<TestObject, bool>> _chain = new List<Func<TestObject, bool>>
    {
        FirstHandler, SecondHandler, FallbackHandler
    };

This is a simple chain consisting of three actions. Each of FirstHandler, SecondHandler and FallbackHandler are methods that match the delegate signature. In this example they are each methods on the same class but this is not mandatory. I’ve defined them as:

private static bool FirstHandler(TestObject testObject)
{
    if (testObject.TestValue != 1)
    {
        return false;
    }

    Console.WriteLine("First Handler");

    return true;
}

private static bool SecondHandler(TestObject testObject)
{
    if (testObject.TestValue != 2)
    {
        return false;
    }

    Console.WriteLine("Second Handler");

    return true;
}

private static bool FallbackHandler(TestObject testObject)
{
    Console.WriteLine(string.Format(CultureInfo.CurrentCulture, "Fallback: {0}", testObject.TestValue));
    return true;
}

The first two methods do a check to see if they are applicable, returning false if this is not the case and true if it is. FallbackHandler is different and always returns true and applies its action. This makes it the last link in the chain.

In order to execute the chain we use the First method from the LINQ Enumerable class. The following example shows the use of the chain to execute (in order) the SecondHandler, FirstHandler and FallbackHandler methods.

_chain.First(c => c(new TestObject {TestValue = 2}));
_chain.First(c => c(new TestObject {TestValue = 1}));
_chain.First(c => c(new TestObject {TestValue = 5}));

This works by enumerating through the _chain collection, executing each delegate in turn. Each method will check whether it wishes to handle the call, returning a value indicating whether it has chosen to do so. A return value of true indicates that a link has handled the request and that no further processing is required. This causes First to stop enumerating. It also returns to matching delegate but this may be ignored. The last handler is a fallback as it handles everything that was not otherwise handled. This is necessary as the First method will throw an exception if no match is found. It is appropriate to do this when there is always an action to be applied. If it is valid that no action be performed then you can substitute FirstOrDefault which will not error when a match is not found.

Note that the chain does not need to be fixed. It is entirely valid to modify it dynamically at runtime. Care should be taken to ensure that there are no threading issues as a result. You can change the Func delegate used provided you continue to return true.

This works well but is not particularly useful when you need the chain to return a value. In this case we can split the check and the action into separate methods. We can make the chain a collection of KeyValuePair values where the key and value types are delegates. In this case the key is a delegate returning true that performs the check and the value is a delegate that performs the action and returns the required value. The chain becomes:

private static readonly ICollection<KeyValuePair<Func<TestObject, bool>, Func<TestObject, int>>> _chain
    = new List<KeyValuePair<Func<TestObject, bool>, Func<TestObject, int>>>
    {
        CreateLink(FirstCheck, FirstAction),
        CreateLink(SecondCheck, SecondAction),
        CreateLink(FallbackCheck, FallbackAction)
    };

private static KeyValuePair<Func<TestObject, bool>, Func<TestObject, int>> CreateLink(Func<TestObject, bool> key,
    Func<TestObject, int> value)
{
    return new KeyValuePair<Func<TestObject, bool>, Func<TestObject, int>>(key, value);
}

We use a helper method here to simplify things given the nested generics. We define the checks and actions as separate methods:

private static bool FirstCheck(TestObject testObject)
{
    return testObject.TestValue == 1;
}

public static int FirstAction(TestObject testObject)
{
    return testObject.TestValue * 2;
}

private static bool SecondCheck(TestObject testObject)
{
    return testObject.TestValue == 2;
}

public static int SecondAction(TestObject testObject)
{
    return testObject.TestValue * 3;
}

private static bool FallbackCheck(TestObject testObject)
{
    return true;
}

public static int FallbackAction(TestObject testObject)
{
    return testObject.TestValue;
}

Invoking the new chain is slightly more complicated and looks like:

var testObject = new TestObject {TestValue = 2};
var result = _chain.First(c => c.Key(testObject)).Value(testObject);

Again the chain may be dynamically altered at runtime provided that this is done in a threadsafe manner. I would recommend reconstructing the entire chain then substituting it for the existing chain rather than attempting to modify an existing chain in place. Modification in place will generally be more complex and require a more complex locking strategy.

This approach demonstrates an implementation that is suitable for many circumstances where a classic chain of responsibility is called for. The use of LINQ methods may have performance implications in some applications and this should be considered before committing to it. In general use however this is a simple way to apply this pattern and avoid verbose for/foreach statements.