C# C语言中的完全惰性管道#
我正在设计一个遵循责任链模式的处理程序管道 管道处理程序具有以下接口:C# C语言中的完全惰性管道#,c#,pipeline,C#,Pipeline,我正在设计一个遵循责任链模式的处理程序管道 管道处理程序具有以下接口: public interface IPipelineHandler<TContext> { Func<TContext, Task> Next { get; set; } Task HandleAsync(TContext context); } 公共接口IPipelineHandler { Func Next{get;set;} 任务HandleAsync(TContext上下文)
public interface IPipelineHandler<TContext>
{
Func<TContext, Task> Next { get; set; }
Task HandleAsync(TContext context);
}
公共接口IPipelineHandler
{
Func Next{get;set;}
任务HandleAsync(TContext上下文);
}
每个处理程序都有一个对管道中下一个处理程序的引用。以下类用于构建管道:
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;
}
}
公共类PipelineBuilder
{
私有只读列表处理程序
=新列表();
公共PipelineBuilder寄存器(IPipelineHandler)
{
添加(handler);
归还这个;
}
公共Func Build()
{
IPipelineHandler root=null;
IPipelineHandler prev=null;
foreach(处理程序中的变量处理程序)
{
if(root==null)
{
根=处理程序;
}
其他的
{
prev.Next=ctx=>handler.HandleAsync(ctx);
}
prev=处理器;
}
返回root.HandleAsync;
}
}
当前实现的缺点是管道中的每个处理程序都是预先构造的。我希望根据需要构造每个处理程序,因此您不需要将处理程序实例传递给构建,而是传递一个Func
我需要对Build()
进行哪些修改才能使用Func
,从而使每个管道处理程序仅在调用时创建
如果不清楚-每个处理程序只应在管道中的前一个处理程序调用时创建,而不是在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);
}
}
公共类LazyPipelineHandler:PipelineHandler
{
私有只读惰性innerHandler;
公共LazyPipelineHandler(Func handlerFactory)
{
this.innerHandler=new Lazy(handlerFactory);
}
公共覆盖任务HandleAsync(TContext上下文,Func下一步)
{
innerHandler.Value.Next=Next;
返回innerHandler.Value.HandleAsync(上下文);
}
}
您可以使用DI或服务定位器,而不是传递IPipelineHandler
实例,您可以使用具体的Type
进行注册,然后使用该Type
按需解析实例传递Func并不困难。我正在努力解决如何懒散地构建管道的问题,即管道的每一步都是按需创建的。我想HttpClient
和ASP.NET Web API服务器的DelegatingHandler
s的组成是您想要的: