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
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)
public interface IActionFilter
{
Task<ResponseMessage> ExecuteActionFilterAsync(ActionContext actionContext, CancellationToken cancellationToken, Func<Task<ResponseMessage>> continuation);
}
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)
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)
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パイプのルールに従って処理することができます.