ASP.NET MVCコントローラアクティブ化(一)


ASP.NET MVCコントローラアクティブ化(一)


前言
ルーティングの章でルーティングの役割を説明し、コントローラの部分について話していますが、本編からMVCのコントローラについて説明します.コントローラはどうやって来ましたか.MVCフレームワークは何をしましたか?前にあった紙面に残された疑問はこの部分で解決されるだろう.
 
 
コントローラのアクティブ化の概要
 
全体的にコントローラのアクティブ化には、次のような手順があります(一部).
 
1.現在のルーティング情報からコントローラ名を取得する
2.現在のシステムのコントローラファクトリを取得する(コントローラを生成する)
2.1コントローラ名生成と現在のシステムの要求コンテキストパラメータによるコントローラタイプ生成(Type)
2.1.1現在のルーティング情報から選択コントローラが存在するネーミングスペースを判断する
2.1.2コントローラタイプを返す(Type)
2.2コントローラタイプ(Type)と要求コンテキストパラメータからコントローラタイプ(IController)を生成する
2.3コントローラタイプを返す(IController)
3.コントローラファクトリで生成されたコントローラを取得する(IController)
4.IController.の実行Execute()
 
コントローラの由来
前述したようにMVCのエントリはModuleにありますが、具体的にはルート登録時にデフォルトの登録MvcHandlerをリクエスト処理タイプとしていますが、コントローラはここで生産されていますが、なぜ生産されているのでしょうか.システムは予めコントローラファクトリクラスのDefaultControllerFactory(以下のコード構造)を実現しているため、コントローラが実行するまでのこの過程で多くのタイプとコントローラのオブジェクトモデルに関連し、これらの内容は後述する.
DefaultControllerFactoryタイプの構造:
 1     public class DefaultControllerFactory : IControllerFactory
 2     {
 3         public DefaultControllerFactory();
 4         public DefaultControllerFactory(IControllerActivator controllerActivator);
 5 
 6         public virtual IController CreateController(RequestContext requestContext, string controllerName);
 7         protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType);
 8         protected internal virtual SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, Type controllerType);
 9         protected internal virtual Type GetControllerType(RequestContext requestContext, string controllerName);
10         public virtual void ReleaseController(IController controller);
11     }

 
本編では、上記の2.1.2の前の部分をざっと説明しますが、まず以下の図をご覧ください.
 
以上のように、ここではコントローラタイプのキャッシュ対象であるControllerType Cacheについて説明するが、ControllerType CacheはIControllerインタフェースを実現したすべての共通クラスをロードMVC-ControllerType Cacheにキャッシュする.xmlファイルにあります.もちろんこれらはすべてフレームワークがしているので、私たちは理解して、その中の思想を学ぶだけでいいです.
リクエストがデフォルトリクエストハンドラに到達すると、デフォルトのコントローラファクトリDefaultControllerFactoryがRouteDataのDataToken【NameSpaces】に定義されたネーミングスペースとValues【controller】のコントローラ名に基づいて判断し、具体的にどのように判断したかはControllerType Cacheオブジェクトによって照会されて一致する.
この名前に対応するコントローラがコントローラ名に基づいてキャッシュに存在するかどうかを問い合せ、存在する場合はILookupタイプオブジェクトに格納し、RouteDataのDataToken【NameSpaces】で定義されたネーミングスペースに基づいてILookupオブジェクトのコントローラタイプが存在するネーミングスペースと比較し、同じ場合は戻りセットにこのタイプを追加します.異なる場合は、RouteDataのDataToken【NameSpaces】の残りのネーミングスペース値を1つずつ比較し続けます.
返されるタイプのセットに応じて、合計が0の場合は空に戻り、合計が1の場合はこのセットのタイプを返し、1より大きい場合はCreateAmbiguousControllerExceptionタイプの例外が発生します.
この時点でDefaultControllerFactoryでコントローラタイプ(Type)が取得されました.
要約2.2で示す部分はIControllerActivatvatorインタフェースタイプの実装である.
 1     //   :
 2     //                            。
 3     public interface IControllerActivator
 4     {
 5         //   :
 6         //                。
 7         //
 8         //   :
 9         //   requestContext:
10         //          。
11         //
12         //   controllerType:
13         //          。
14         //
15         //     :
16         //           。
17         IController Create(RequestContext requestContext, Type controllerType);

この部分の実現は、コントローラ工場に注入することができ、実現の内部には依然として拡張注入可能な場所があり、MVCフレームワークにはデフォルトの実現があり、2.2部分以降の実現概念図を見てみましょう.
ControllerのTypeを取得した後、DefaultControllerFactoryはTypeに基づいてControllerを作成することができるが、MVCフレームワークの設計では、「ControllerTypeに基づいてControllerを作成する方法」はDefaultControllerFactoryには置かれず、MVCフレームでIControllerActivvatorインタフェースタイプを実現したデフォルト実装クラスDefaultControllerActivvatorタイプによってIControllerを作成するものであり、一方、DefaultControllerActivvatorでは、DependencyResolverタイプによってIDependencyResolverインタフェースのデフォルト実装クラスを作成することで実現されます.
IDependencyResolverインタフェースには、最終的にタイプを作成するために使用される方法であるGetService()メソッドがあり、カスタマイズして実装することもできます.これも拡張点の1つです.インタフェースタイプといえば、MVCにはIDependencyResolverインタフェースをデフォルトで実現するタイプのDefaultDependencyResolver、DefaultDependencyResolverタイプのGetService()メソッドのデフォルト実装方式Activatvatorがある.CreateInstance(serviceType);つまり、通常は反射によってタイプが作成されます.
HandlerからIcontrollerまでのプロセス図を見てみましょう.
上記および前編ではMVCのデフォルト実装方式であり、各部分をカスタマイズして拡張することができ、MvcHandler、DefaultControllerFactory、DefaultDependencyResolverなどのタイプがある.
コントローラのアクティブ化中に注入可能なすべての拡張点が後述します.