我正在设计一个遵循责任链模式的处理程序管道.
管道处理程序具有以下接口:
public interface IPipelineHandler<TContext>
{
Func<TContext, Task> Next { get; set; }
Task HandleAsync(TContext context);
}
每个处理程序都引用了管道中的下一个处理程序.以下类用于构建管道:
public class PipelineBuilder<TContext>
{
private readonly List<IPipelineHandler<TContext>> handlers
= new List<IPipelineHandler<TContext>>();
public PipelineBuilder<TContext> Register(IPipelineHandler<TContext> handler)
{
handlers.Add(handler);
return this;
}
public Func<TContext, Task> Build()
{
IPipelineHandler<TContext> root = null;
IPipelineHandler<TContext> prev = null;
foreach (var handler in handlers)
{
if (root == null)
{
root = handler;
}
else
{
prev.Next = ctx => handler.HandleAsync(ctx);
}
prev = handler;
}
return root.HandleAsync;
}
}
当前实现的缺点是管道中的每个处理程序都是预先构建的.我想按需构造每个处理程序,而不是将处理程序实例传递给构建,而是传递一个Func< IPipelineHandler< TContext>>.
我需要对Build()进行哪些修改才能使用Func< IPipelineHandler< TContext>>这样每个管道处理程序只在调用时创建?
如果不清楚 – 每个处理程序只应在管道中的前一个处理程序调用时创建,而不是在Build()方法期间创建.
最佳答案 最终解决方案非常简单.我创建了一个LazyPipelineHandler包装器,这样我仍然可以构建管道但不实例化包装的处理程序,直到它实际需要执行:
public class LazyPipelineHandler<TContext> : PipelineHandler<TContext>
{
private readonly Lazy<IPipelineHandler<TContext>> innerHandler;
public LazyPipelineHandler(Func<IPipelineHandler<TContext>> handlerFactory)
{
this.innerHandler = new Lazy<IPipelineHandler<TContext>>(handlerFactory);
}
public override Task HandleAsync(TContext context, Func<TContext, Task> next)
{
innerHandler.Value.Next = next;
return innerHandler.Value.HandleAsync(context);
}
}