Search code examples
c#design-patternschain-of-responsibility

Chain of Responsibility Dynamic Chain


I am working on a application that uses a chain of responsibility to process a request. I know how to build the chain, but if you look at the example below, I would have to call link1.Process(request); to initiate the chain process. What I am trying to figure out is, is there a way to treat this like a collection can just call the first link of the chain, whatever that may be? The reason being is, I know what the base element is (the final default object), but other programmers could add objects into the chain and could potentially put them in a position where the chain would never get to them.

public class MergedFieldProcessor
{

    public MergedFieldProcessor()
    {
        //Define CoR here

       FieldProcessor link1 = new FieldProcessor();
       FieldProcessor link2 = new FieldProcessor();
       FieldProcessor link3 = new FieldProcessor();

       link1.SetNextProcessor(link2);
       link2.SetNextProcessor(link3);

    }



}

public abstract class FieldProcessor
{
    private FieldProcessor NextProcessor { get; set; }

    public FieldProcessor()
    {
        this.NextProcessor = new SprocObject();
    }

    public void SetNext (FieldProcessor successor)
    {
       this.NextProcessor = successor;
    }

    //determines if this link in the change is responsible for the request
    public abstract Boolean WillProcess(MergedFieldProcessorRequest request);

    //performs the processing required for the tag
    public abstract void ProcessField(MergedFieldProcessorRequest request);


    //chain method that passes the request
    public void ProcessRequest(MergedFieldProcessorRequest request)
    {
        if (!this.WillProcess(request))
            this.NextProcessor.ProcessRequest(request);
        else
            this.ProcessField(request);
    }


}

public class MergedFieldProcessorRequest
{
    public MergedField Field { get; set; }

    public Dictionary<string, string> SearchParams { get; set; }
}

Example of unreachable links:

FieldProcessor link1 = new FieldProcessor();
        FieldProcessor link2 = new FieldProcessor();
        FieldProcessor link3 = new FieldProcessor();
        FieldProcessor link4 = new FieldProcessor();

        link4.SetNext(link1);
        link1.SetNext(link2);
        link2.SetNext(link3);

if they didn't modify the code where the process is initated to say link4.Process(request), then link4 would never be a part of the chain.

In short, is it possible to dynamically build the chain so that if someone adds the object to the collection, it automatically gets added into the chain?


Solution

  • Here is the solution I came up with. Just add each processor to a collection and then iterate over that collection to build the chain, and to process the chain, simply call this.Links[0].Process(request);

     #region Build Chain Collection;
            this.Links = new List<FieldProcessor>()
            {
                new StudentEnrollmentDetailsProcessor(),
                new SprocObject()
            };
            #endregion; 
    
            #region Build Chain Dynamically
            for (int i = 0; i < this.Links.Count(); i++)
            {
                if (i < this.Links.Count())
                {
                    this.Links[i].SetNext(this.Links[i + 1]);
                }
            }
            #endregion;