Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/296.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C语言中的完全惰性管道#_C#_Pipeline - Fatal编程技术网

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的组成是您想要的: