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は異なるインスタンスである可能性がありますが、一般的なコントラクトに拘束されます。タスクの1つは、着信オブジェクトを完全に異なるオブジェクトにマッピングし、そこからそのインスタンスを転送することです。

ご覧のとおり、パイプラインですべてのタスクを実行しています。これを次のように変更します。

  • 次のタスクのメソッドの入力はExecute、以前に実行されたタスクからのものである必要があります。
  • タスクが失敗した場合CanExecute、パイプラインはタスクの処理を停止する必要があります。

これを手に入れるのを手伝ってくれませんか。また、この目的のためにコードが異なる構造になることを期待しますか?

4

2 に答える 2

3

この実装では、CanProcessは実際にプロセスを停止する例外をトリガーするために使用されます。

ExecuteWithPartial期待する動作である場合に備えて、例外を処理する、と呼ばれる2番目の実装を追加しました。処理しますが、エラーが発生した場合は、その時点までの部分的な結果を返します。

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
{
}
于 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 に答える