我有一系列任务,基本上是责任链模式的变体。
我的管道中的任务如下所示
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
未能完成任务,则管道应停止处理任务。你能帮我解决这个问题。您是否还希望为此目的以不同的方式构建代码?
答案 0 :(得分: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
{
}
答案 1 :(得分: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-ish。但更重要的是要注意它是否满足您的需求,而不是使用正确的设计模式术语。 :)