あなたをオープンソースに連れて行きます-ASP.NET_MVC(二)
6505 ワード
前の記事では全体的にASPを紹介しています.NET MVCのリクエスト処理フローは、「ルーティング」、「コントローラ」、「ビュー」および「モデル」に大別され、以下、フロー順に展開される.
一、ルート
ルーティングといえば、実際にはASP.NETのコアルーティングエンジンとMVCルーティング.コアルーティングエンジンはオープンソースではありません(マイクロソフトは手を残しています).ブラウザから送られてきたURLを解析し、コントローラを割り当てます.
ここでは、IrouteHandlerインタフェースを明示的に実装したMvcRouteHandlerというMVCルーティングを解析します.GetHttpHandlerメソッドはMvcHandlerオブジェクトを返し、MvcHandlerはIHttpHandlerインタフェースを実装しているので、次のようなProcessRequestメソッドが含まれています.
コードセグメント1
このプロセスリクエストの方法は、皆さんも顔見知りだと思いますよね?いいですね.ASPにいます.NET WebFormの開発では、一般的なハンドラ、すなわち.ashxファイル、このファイルのクラスはIHttpHandlerインタフェースを実現し、ProcessRequestメソッドもあります.
さて、このProcessRequestメソッドは、ルーティングがコントローラに位置決めされた後に実行されるコア操作です.つまりcontroller.Execute(RequestContext)文の実行により、HTML応答の生成とブラウザへの返信が発生します.簡単でしょう?私たちはここで最も核心的で、最も骨格的な部分に言及しただけで、細部には触れていません.枝葉末節に邪魔されないようにしています.次にコントローラを分析します.
二、コントローラ
コードセグメント1のcontrollerは、インタフェースIControllerの一例であり、インタフェースIControllerは簡単であり、次のような方法しかありません.
一、ルート
ルーティングといえば、実際にはASP.NETのコアルーティングエンジンとMVCルーティング.コアルーティングエンジンはオープンソースではありません(マイクロソフトは手を残しています).ブラウザから送られてきたURLを解析し、コントローラを割り当てます.
ここでは、IrouteHandlerインタフェースを明示的に実装したMvcRouteHandlerというMVCルーティングを解析します.GetHttpHandlerメソッドはMvcHandlerオブジェクトを返し、MvcHandlerはIHttpHandlerインタフェースを実装しているので、次のようなProcessRequestメソッドが含まれています.
protected internal virtual voidProcessRequest(HttpContextBase httpContext)
{
IController controller;
IControllerFactory factory;
ProcessRequestInit(httpContext, outcontroller, out factory);
try
{
controller.Execute(RequestContext);
}
finally
{
factory.ReleaseController(controller);
}
}
コードセグメント1
このプロセスリクエストの方法は、皆さんも顔見知りだと思いますよね?いいですね.ASPにいます.NET WebFormの開発では、一般的なハンドラ、すなわち.ashxファイル、このファイルのクラスはIHttpHandlerインタフェースを実現し、ProcessRequestメソッドもあります.
さて、このProcessRequestメソッドは、ルーティングがコントローラに位置決めされた後に実行されるコア操作です.つまりcontroller.Execute(RequestContext)文の実行により、HTML応答の生成とブラウザへの返信が発生します.簡単でしょう?私たちはここで最も核心的で、最も骨格的な部分に言及しただけで、細部には触れていません.枝葉末節に邪魔されないようにしています.次にコントローラを分析します.
二、コントローラ
コードセグメント1のcontrollerは、インタフェースIControllerの一例であり、インタフェースIControllerは簡単であり、次のような方法しかありません.
<pre name="code" class="csharp"> public interface IController
{
void Execute(RequestContextrequestContext);
}
代码段 2
Controller的实例化是由【ProcessRequestInit(httpContext, out controller, out factory)】这个语句完成的,下面我们看一下ProcessRequestInit这个方法中实例化Controller的部分,不考虑细节,直奔主题。
private voidProcessRequestInit(HttpContextBase httpContext, out IController controller, outIControllerFactory factory) { // If request validation hasalready been enabled, make it lazy. This allows attributes like [HttpPost](which looks // at Request.Form) to workcorrectly without triggering full validation. // Tolerate null HttpContext fortesting. HttpContext currentContext =HttpContext.Current; if (currentContext != null) { bool?isRequestValidationEnabled =ValidationUtility.IsValidationEnabled(currentContext); if (isRequestValidationEnabled== true) { ValidationUtility.EnableDynamicValidation(currentContext); } } AddVersionHeader(httpContext); RemoveOptionalRoutingParameters(); // Get the controller type string controllerName =RequestContext.RouteData.GetRequiredString("controller"); // Instantiate the controller andcall Execute factory =ControllerBuilder.GetControllerFactory(); controller =factory.CreateController(RequestContext, controllerName); if (controller == null) { throw newInvalidOperationException( String.Format( CultureInfo.CurrentCulture, MvcResources.ControllerBuilder_FactoryReturnedNull, factory.GetType(), controllerName)); } }
コードセグメント3
コードセグメント3の「コントローラ=factory.CreateController(RequestContext,controller Name)」文は、ルーティングシステムによって位置決めされたコントローラ情報(すなわち、Controllerフォルダで定義された各コントローラクラス)に基づいて、反射によってコントローラオブジェクトを作成するコントローラをインスタンス化する場所である.もちろん、コントローラ工場、検証の要求など、実装の詳細はたくさんありますが、脈絡を明確に保つために、ここで省略します.後述します.
IControllerインタフェースはMVCにいくつかの内蔵実装クラスがあり、ControllerBaseおよびIAsyncControllerを含むが、ControllerはControllerBaseのサブクラスであり、最も一般的なコントローラベースクラスである.
実際には、IControllerを自分で実現することができます.例えば、publicclass MyController : IController { public voidExecute(RequestContext requestContext) { requestContext.HttpContext.Response.Write(“Hello”); } }
コードセグメント4
どうですか.SoEasy!大きなRazorエンジンなどを使わなくてもいいです.しかし、このようにすると非常に強い結合を招き、HTMLを自分で解析する必要があります.これは疲れた仕事です.
MVCのControllerクラスがどのように実現されているかを見てみましょう.ControllerはControllerBaseクラスに継承され、ControllerBaseはExecuteメソッド(コードセグメント5)を実装し、ControllerはControllerBaseのExecuteCoreメソッド(コードセグメント6)を書き換えた.
protected virtual voidExecute(RequestContext requestContext) { if (requestContext == null) { throw newArgumentNullException("requestContext"); } if (requestContext.HttpContext ==null) { throw newArgumentException(MvcResources.ControllerBase_CannotExecuteWithNullHttpContext,"requestContext"); } VerifyExecuteCalledOnce(); Initialize(requestContext); using(ScopeStorage.CreateTransientScope()) { ExecuteCore(); } }
コードセグメント5
protected override void ExecuteCore() { // If code in this method needs tobe updated, please also check the BeginExecuteCore() and // EndExecuteCore() methods ofAsyncController to see if that code also must be updated. PossiblyLoadTempData(); try { string actionName =GetActionName(RouteData); if(!ActionInvoker.InvokeAction(ControllerContext, actionName)) { HandleUnknownAction(actionName); } } finally { PossiblySaveTempData(); } }
コードセグメント6
ExecuteCoreメソッドを見てみましょう.そのコア文は「if(!ActionInvoker.InvokeAction(ControllerContext,actionName)」です.この文は特定のActionを実行する場所で、その文が実行されるとHTTP応答がブラウザに返されます.ここではActionInvokerを使いました.ActionInvokeActionメソッドで、ActionInvokerはIActionInvokerインタフェースの例であり、このインタフェースの定義もかなり簡単で、以下のようにします.public interface IActionInvoker { bool InvokeAction(ControllerContextcontrollerContext, string actionName); }
コードセグメント7
MVCに内蔵されているIActionInvoker実装クラスには、ControllerActionInvokerとIAsyncActionInvokerがあり、後者は非同期クラスであるが、それにかかわらずControllerActionInvokerを重点的に分析する.
ControllerActionInvokerのInvokeActionメソッドの実装は複雑で、約90行のコードがあります.今日は少し疲れたので、明日続けます.