责任链动态链

时间:2013-08-02 20:36:35

标签: c# design-patterns chain-of-responsibility

我正在开发一个使用责任链来处理请求的应用程序。我知道如何构建链,但是如果你看下面的例子,我将不得不调用link1.Process(request);来启动链式流程。我想弄清楚的是,是否有一种方法可以像处理集合那样对待链接的第一个链接,无论可能是什么?原因是,我知道基本元素是什么(最终的默认对象),但是其他程序员可以将对象添加到链中,并且可能将它们放在链永远不会到达它们的位置。

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永远不会成为链的一部分。

简而言之,是否可以动态构建链,以便如果有人将对象添加到集合中,它会自动添加到链中?

4 个答案:

答案 0 :(得分:1)

您是否希望为用户提供构建链的能力......而无法构建链? 用户负责链接对象,或抛弃链接并为FieldProcessor提供任何集合(然后按顺序调用它们)。

如果链接很重要,那么您可以做的最好的事情是在处理之前对循环和无法访问的链接进行链式验证。

答案 1 :(得分: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;

答案 2 :(得分: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后继者,通常它必须是一个更接近链(将处理任何请求)。

答案 3 :(得分:0)

class SomeClass
{
  private StringBuilder _sb = new StringBuilder();
  private SerialPort serialPort1 

  [...]

  void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) 
  {
    if (e.EventType == SerialData.Chars)
    {
       _sb.Append(serialPort1.ReadExisting());
    }
    else
    {
       MessageBox.Show(_sb.ToString());
       _sb.Clear();
    }
  }
}

并将它们用作

public abstract class AbCommon
{
    public virtual AbCommon Successor { get; protected set; }

    public virtual void Execute()
    {           
        if (Successor != null)
        {
            Successor.Execute();
        }
    }

    public virtual void SetSuccessor(AbCommon successor)
    {
        if (Successor != null)
        {
            Successor.SetSuccessor(successor);
        }
        else
        {
            this.Successor = successor;
        }
    }
}

class DefaultClass : AbCommon
{   
    public override void Execute()
    {
        Console.WriteLine("DC");
        base.Execute();
    }       
}

class FirstClass: AbCommon
{
    public override void Execute()
    {
        Console.WriteLine("FC");
        base.Execute();
    }
}

class SecondClass: AbCommon
{   
    public override void Execute()
    {
        Console.WriteLine("SC");
        base.Execute();
    }
}

class ThirdClass: AbCommon
{
    public override void Execute()
    {
        Console.WriteLine("TC");
        base.Execute();
    }
}

您可以动态添加或删除对象