5

我有一个任务管道,基本上是责任链模式的变体。

我的管道中的一个任务如下所示

internal interface IPTask<T>
{
    bool CanExecute(T instance);
    T Process(T instance);
}

..我的处理器看起来像

internal interface IProcessor<T>
{
    T Execute(T instance);
}

我的具体实现如下所示:

public class Processor<T> : IProcessor<T>
{
    private readonly ITasks<T> tasks;

    public Processor(ITasks<T> tasks)
    {
        this.tasks= tasks;
    }

    public T Execute(T instance)
    {
         var taskstoExecute = tasks.GetTasks()
                                   .Where(task => task.CanExecute(instance));

         taskstoExecute.ToList().ForEach(task=>task.Process(instance));

         return T;
    }
}

..我的任务如下所示:

internal interface ITasks<T>
{
    IEnumerable<IPTask<T>> GetTasks();
}

T 可以是不同的实例,但受通用合同的约束。其中一项任务是将传入对象映射到完全不同的对象并从那里转发该实例。

现在如您所见,我正在执行管道中的所有任务,我想将其修改为以下内容:

  • 下一个任务的方法的输入Execute应该来自先前执行的任务。
  • 如果CanExecute任务失败,则管道应停止处理任务。

你能帮我弄到这个吗?此外,您是否希望为此目的代码结构不同?

4

2 回答 2

3

使用此实现,CanProcess实际用于触发将停止进程的异常。

我添加了第二个实现,称为ExecuteWithPartial,它处理异常,以防这是您所期望的行为。它会处理,但如果有错误,它会返回到该点的部分结果。

public class Processor<T> : IProcessor<T>
{
    //... rest of your code

    public T Execute(T instance)
    {
        return this._tasks.GetTasks().Aggregate(instance, (current, task) => InternalExecute(task, current));
    }

    public T ExecuteWithPartial(T instance)
    {
        var target = instance;
        try
        {
            foreach (var task in this._tasks.GetTasks())
            {
                target = InternalExecute(task, target);
            }
            return target;
        }
        catch (CantExecuteException)
        {
            return target;
        }
    }


    private static T InternalExecute(IPTask<T> task, T instance)
    {
        if (!task.CanExecute(instance))
            throw new CantExecuteException();
        return task.Process(instance);
    }
}

新的异常类是:

public class CantExecuteException : Exception
{
}
于 2012-06-21T22:38:05.867 回答
3

这个怎么样:

public T Execute(T instance)
{
     T result = instance;
     foreach(var individual in tasks.GetTasks())
     {
         if(!individual.CanExecute()) break;

         result = individual.Process(result);
     }

     return result;
}

正如您目前所拥有的,它更像是一种复合模式,而不是责任链。这种变化使它更接近于 CoR。但更重要的是要注意它是否满足您的需求,而不是使用正确的设计模式行话。:)

于 2012-06-22T04:56:05.353 回答