c# - Modified Chain Of Responsibility -


i quite understand basics of chain of responsibility pattern. however, ask if possible set next receiver in sequence dynamically.

the basic idea depending on sequence of approver, instantiate next object.

below example:

abstract base class

public abstract class approvercategorizer {     protected approvercategorizer nextapprover { get; private set; }      public approvercategorizer registernextapprover(approvercategorizer nextapprover)     {         nextapprover = nextapprover;         return nextapprover;     }      public abstract void approveamount(testentity entity);      protected bool islast(queue<string> approverqueue)     {         return string.isnullorempty(approverqueue.peek());     } } 

officer approver class

public class officeraapprover : approvercategorizer {     public override void approveamount(testentity entity)     {         entity.approverqueue.dequeue();          if (entity.amount <= 300)         {             entity.status = "approved";             return;         }          if (!islast(entity.approverqueue) && string.isnullorwhitespace(entity.status))         {             nextapprover.approveamount(entity);             return;         }         else         {             entity.status = "rejected";         }      }  } 

officer b class

public class officerbapprover : approvercategorizer {     public override void approveamount(testentity entity)     {         entity.approverqueue.dequeue();          if (entity.amount <= 300)         {             entity.status = "approved";             return;         }          if (!islast(entity.approverqueue) && string.isnullorwhitespace(entity.status))         {             nextapprover.approveamount(entity);             return;         }         else         {             entity.status = "rejected";         }      }  } 

approver chain class

public class approverchain {     public static testentity entity { get; set; }     public static approvercategorizer approver { get; set; }      public approverchain()     {         list<string> approverlist = entity.approverlist.split(',').tolist();         queue<string> approverqueue = new queue<string>();          approver = new startapprover();         // note: code below working, not desired logic.         //approver.registernextapprover(new officeraapprover()).registernextapprover(new officerbapprover());          // note: code below not working, desired logic.         foreach (string approver in approverlist)         {             switch (approver)             {                 case "officera":                     approver.registernextapprover(new officeraapprover());                     break;                 case "officerb":                     approver.registernextapprover(new officerbapprover());                     break;             }             approverqueue.enqueue(approver);          }          entity.approverqueue = approverqueue;      }      public string startprocess()     {         approver.approveamount(entity);         return entity.status;     } } 

business class

public string processapproval() {   testentity entity = new testentity   {      amount = 500,      approverlist = "officerb,officera"   };    approverchain.entity = entity;   approverchain chain = new approverchain();   var result = chain.startprocess();    return result; } 

this means officerb class process first. if fails, go officera class.

is there way tweak desired logic mentioned? if so, how done?

if understand correctly, need configure approvers via runtime value (string in case).

with little change in code possible. here required modification.

public approverchain() {     list<string> approverlist = entity.approverlist.split(',').tolist();     queue<string> approverqueue = new queue<string>();      approver = new startapprover();      approvercategorizer currentapprover = approver;     foreach (string approver in approverlist)     {         switch (approver)         {             case "officera":                 currentapprover = currentapprover.registernextapprover(new officeraapprover());                 break;             case "officerb":                 currentapprover = currentapprover.registernextapprover(new officerbapprover());                 break;         }         approverqueue.enqueue(approver);     }      entity.approverqueue = approverqueue; } 

above code work fine. me approverqueue looks fishy.

it seems you're having approverqueue property find out whether current approver last approver in chain. can find checking nextapprover null , rid of approverqueue.

then code becomes

public class approverchain {     public static testentity entity { get; set; }     public static approvercategorizer approver { get; set; }      public approverchain()     {         approver = new startapprover();          list<string> approverlist = entity.approverlist.split(',').tolist();          approvercategorizer currentapprover = approver;         foreach (string approver in approverlist)         {             switch (approver)             {                 case "officera":                     currentapprover = currentapprover.registernextapprover(new officeraapprover());                     break;                 case "officerb":                     currentapprover = currentapprover.registernextapprover(new officerbapprover());                     break;             }         }     }      public string startprocess()     {         approver.approveamount(entity);         return entity.status;     } }  public abstract class approvercategorizer {     protected approvercategorizer nextapprover { get; private set; }      public approvercategorizer registernextapprover(approvercategorizer nextapprover)     {         nextapprover = nextapprover;         return nextapprover;     }      public abstract void approveamount(testentity entity);      protected bool islast()     {         return nextapprover == null;     } }  public class officeraapprover : approvercategorizer {     public override void approveamount(testentity entity)     {         if (entity.amount <= 300)         {             entity.status = "approved";             return;         }          if (!islast() && string.isnullorwhitespace(entity.status))         {             nextapprover.approveamount(entity);             return;         }         else         {             entity.status = "rejected";         }     } } 

and testentity class not have approverqueue property.


Comments

Popular posts from this blog

node.js - Mongoose: Cast to ObjectId failed for value on newly created object after setting the value -

[C++][SFML 2.2] Strange Performance Issues - Moving Mouse Lowers CPU Usage -

ios - Possible to get UIButton sizeThatFits to work? -