Responsibility chain implementation

I have a task pipeline, which is basically a variation of the chain of responsibility scheme.

The task in my pipeline is below

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

.. and my processor looks like

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

and my specific implementation is as follows:

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

.. and my tasks look like this:

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

T can be different copies, but are bound by a common agreement. One of the tasks is to map the incoming object to a completely different object and forward this instance from there.

Now, as you can see, I perform all the tasks in the pipeline, I would like to change this to the following:

  • The input for the method Executefor the next task must be made from a previously completed task.
  • If CanExecutenot executed for the task, then the pipeline should stop processing the tasks.

. , - ?

+5
2

:

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-ish. , , .:)

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

Exception:

public class CantExecuteException : Exception
{
}
+3

All Articles