2013-08-02 2 views
0

Я работаю над приложением, которое использует цепочку ответственности для обработки запроса. Я знаю, как построить цепочку, но если вы посмотрите на приведенный ниже пример, мне нужно позвонить link1.Process(request);, чтобы инициировать процесс цепочки. То, что я пытаюсь понять, заключается в том, есть ли способ относиться к этому, так как коллекция может просто называть первое звено цепи, что бы это ни было? Причина в том, что я знаю, что такое базовый элемент (конечный объект по умолчанию), но другие программисты могли добавлять объекты в цепочку и могли потенциально поставить их в положение, когда цепочка никогда не доберется до них.Цепь ответственности Dynamic Chain

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

Пример недостижимых ссылки:

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

, если они не изменили код, в котором процесс Инициировано сказать link4.Process(request), то link4 никогда не будет частью цепи.

Короче говоря, можно динамически построить цепочку, так что если кто-то добавляет объект в коллекции, он автоматически добавляется в цепи?

+1

Вы слишком много думаете об этом. Если ваш потребитель упустил ссылку, это было более чем вероятно специально. Если они этого не сделали, это их вина. Это похоже на принуждение компилятора к тому, чтобы цикл while был закрыт только потому, что можно использовать цикл while для создания бесконечного цикла. –

+0

Все это похоже на то, что вы не используете ни одну из полезных функций C# и .Net. Какова реальная потребность в этом? Я уверен, что есть намного лучшие способы добиться того, что вам нужно, например, MEF. –

ответ

0

Вот решение, которое я придумал. Просто добавьте каждый процессор в коллекцию, а затем перебрать эту коллекцию, чтобы построить цепочку, и обработать цепочку, просто вызовите 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; 
1

Вы хотите, чтобы дать пользователям возможность создавать цепочки ... без возможности построения цепочек?
Либо пользователь отвечает за сцепление объектов, или бросить сцепление прочь и предоставить любую коллекцию для FieldProcessor с (а затем вызвать их, чтобы они в коллекции).

Если сцепление важно, лучшее, что вы можете сделать, это проверка цепи для циклов и недостижимых звеньев до обработки.

0

вы могли бы использовать отражение и немного рекурсии

public class MergedFieldProcessor 
{ 
    private FieldProcessor first; 

    private FieldProcessor CreateLink(IEnumerator<Type> processors) 
    { 
     if(processors.MoveNext()) 
     { 
      FieldProcessor link = (FieldProcessor)Activator.CreateInstance(processors.Current); 
      link.NextProcessor = CreateLink(processors); 
      return link; 
     } 
     return null; 
    } 

    public MergedFieldProcessor() 
    { 
     var processType = typeof(FieldProcessor); 
     var allProcess = processType.Assembly.GetTypes() 
      .Where(t => t != processType && processType.IsAssignableFrom(t)); 
     first = CreateLink(allProcess.GetEnumerator()); 
    } 

    public void Handle(MergedFieldProcessorRequest request) 
    { 
     first.ProcessRequest(request); 
    } 
} 

это обеспечит создание и соединение всех возможных ссылок вместе с предостережением: последняя ссылка будет иметь преемник null и, как правило, она должна быть ближе к цепочке (будет обрабатывать любой запрос).

Смежные вопросы