Mike Mike - 2 months ago 7
C# Question

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?

Answer

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;
Comments