2016-06-24 7 views
4

私は責任チェーンパターンに従ったハンドラパイプラインを設計しています。C#の完全な遅延パイプライン

パイプラインハンドラは、以下のインターフェースを有する。

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>>を渡します。

Func<IPipelineHandler<TContext>>と連携するために、どのパイプラインハンドラが呼び出されたときにのみ作成されるようにするために、どのような変更をBuild()にする必要がありますか?

明らかでない場合 - 各ハンドラは、パイプラインの前のハンドラによって呼び出されたときにのみ作成され、Build()メソッドでは呼び出されません。

+1

、代わりに 'を渡す:私は、私はまだそれが実際に実行することが必要になるまでラップハンドラをインスタンス化パイプラインを構築したができなかったようにLazyPipelineHandlerラッパーを作成しました具体的な 'Type'を使って登録し、その' Type'を使ってオンデマンドでインスタンスを解決することができます。 – Luiso

+0

Funcを渡すことは難しくありません。私はパイプラインを遅延的に構築する方法、すなわちパイプラインの各ステップが必要に応じて作成されることに苦労しています。 –

+0

'HttpClient'とASP.NET Web APIサーバのための' DelegatingHandler'の構成はあなたが望むものだと思います:https://github.com/ASP-NET-MVC/aspnetwebstack/blob/master/src/System .Net.Http.Formatting/HttpClientFactory.cs#L57-L89 – tugberk

答えて

1

解決策は結局かなり簡単でした。 *あなたは*のDI *または*サービスロケータを使用することができます

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); 
    } 
} 
関連する問題