ASP.NET WebAPI 14擬似Filterパイプ

3306 ワード

WebAPIには、HttpMessageHandler、ActionFilter、ExceptionFilterのようないくつかのパイプ(Channel)が設計されています.3つのパイプのうちHttpMessageHandlerパイプとExceptionFilterパイプはレベル設計に基づいており、ActionFilterパイプはメソッドレベル設計に基づいている.ActionFilterパイピングについては、AOPのアイデアを採用しているので、方法レベルで設計されています.
WebAPIのソースコードを見ているうちにActionFilterパイプラインでどのように表現されているかを示すツリーや閉パッケージなどの内容を書く前に手をつけたことがないので、簡単版のActionFilterを真似て手を練習したいと思っています.
 
demoを書く過程で、私はActionの戻り値をResponseMessageに固定し、ActionFilter実現過程でWebAPIの具体的な規則に従っていないが、ActionFilterのAction実行前後への切り込みとマルチActionFilterの注入を実現するだけである.
 

IActionFilter


 
public interface IActionFilter

 { 

Task<ResponseMessage> ExecuteActionFilterAsync(ActionContext actionContext, CancellationToken cancellationToken, Func<Task<ResponseMessage>> continuation); 

 }

 
 
 
 
IActionFilter私は直接Copyソースコードの中にあります.IActionFilterインタフェースは、ExecuteActionFilterAsyncメソッドを1つだけ定義しています.メソッドの最初の2つのパラメータについてはよく理解され、最後のタイプがFuncのパラメータcontinuationであることは、ActionFilterを構成する鍵である.WebAPIでは、すべてのActionおよびIActionFilterのExecuteActionFilterAsyncメソッドを閉パッケージ化してFunc、さらに各FuncをActionFilterに段階的に追加して、ActionFilterパイプライン全体の構築を完了します.
 

ActionからFunc<Task<ResponseMessage>>へ


Actionの場合、戻り値をResponseMessageとデフォルト設定しているので、戻り値を変換していません.Func>は無参の依頼なので、Func>への変換は2つのステップに分かれています.
  • 定義クラスActionInvoker(demoではそのクラス自体が必須ではなく、このクラスを主に練習表現ツリーとして定義する)
  • ActionInvokerに対してFunc
  • を生成
     
    Func<Task<ResponseMessage>> result = () => 
    
     { 
    
    return invoker.Invoke(context, cancellationToken); 
    
    };
    

     
     
     
     
     

    閉パッケージによるActionFilterパイプの生成


    IActionFilterのExecute ActionFilterAsyncメソッドをFunc>に変換し、ActionFilterパイプラインに段階的に追加することは前述していますが、この場合は閉パッケージを使用する必要があります.
     
     
    ActionInvoker invoker = new ActionInvoker(context.Action); 
    
     
    
    Func<Task<ResponseMessage>> result = () => 
    
     { 
    
    return invoker.Invoke(context, cancellationToken); 
    
     }; 
    
     
    
    for (int i = 0; i <= filters.Count - 1; i++) 
    
     { 
    
    IActionFilter filter = filters[i]; 
    
     
    
    Func<Func<Task<ResponseMessage>>, IActionFilter, Func<Task<ResponseMessage>>> chainContinuation = 
    
     (continuation, innerFilter) => 
    
     { 
    
    return () => 
    
     { 
    
    return innerFilter.ExecuteActionFilterAsync(context, cancellationToken, continuation); 
    
     }; 
    
     }; 
    
     result = chainContinuation(result, filter); 
    
     }
    

     
     
     
    このコピーされたActionFilterは比較的簡単なので、後でExceptionパイプを入れることができるかどうかを見ながら、WebAPIのActionFilterパイプのルールに従って処理することができます.
     

    ソースコード


       
    Github: https://github.com/BarlowDu/WebAPI (FilterChannelDemo)