007.ASP.NET MVCコントローラ依存注入

21594 ワード

原文リンク:http://www.codeproject.com/Articles/560798/ASP-NET-MVC-Controller-Dependency-Injection-for-Be
前言:この文章では、MVCフレームワークに注入された使用に依存することをdemoを通じて率直に説明します.
コンテンツリスト:
  1.紹介する
  2.なぜコントローラ依存注入を使用するのか
  3.コントローラ静的構造
  4.カスタムコントローラ
  5.Frameworkでのコントローラの作成
  6.コントローラファクトリモードを使用する理由
  7.コントローラファクトリモード
    7.1.ターゲット1
    7.2.ターゲット2
  8.MEFによるコントローラファクトリモードの実装
  9.重点的に補充する.
一:紹介
  
まずコントローラがMVCフレームワークでやるべきことを簡単に説明します
  1.HTTPリクエスト受信
  2.HTTPリクエストの処理
  3.クライアント入力データの操作
  4.クライアントに返信を送信
  5.ModelとViewの中継所として
MVCフレームワークは実行時に自分でコントローラオブジェクトを作成し、コントローラクラスの構築関数がパラメータなしであるという前提条件がある.コントローラのパラメータとしてオブジェクトを渡したい場合は、どうすればいいですか?このタイプのコントローラを作成すると失敗します.独自のコントローラを作成し、コントローラパラメータをコントローラに注入する必要があります.
パラメータをコントローラの構造方法に注入する方法はいくつかあります.
  1.属性の設定
  2.方法を通す
  3.構築方法
この論文では,コントローラを用いてMVCのコンストラクション関数に注入する方法を説明する.カスタムコントローラファクトリモードを使用しないと、コントローラ注入は実現できません.もちろん、簡単なコントローラファクトリを作成し、MVCフレームワークに登録する方法も説明します.私もコントローラに注入する方法を示し、MEFを使用します.
二.なぜコントローラ注入を使うのか
現実のプログラム開発では、ほとんどのMVCプログラムが依存するコンポーネントを注入する必要があることがわかります.コンポーネントをコントローラに直接作成することができ、注入する必要はありません.この場合、コンポーネントとコントローラは緊密に結合されており、コンポーネントの拡張が変更されたり、新しいバージョンのコンポーネントが使用される場合は、コントローラの実装を変更する必要があります(PS:コントローラ注入の使用方法を説明します)
ユニットテストを使用したい場合は、別の困難に直面する可能性があります.これらのコントローラを独立したユニットでテストすることはできません.新しい特性を真似することはできません.真似できないと、独立した環境でコードを実行することはできません.
三.コントローラ静的構造
MVCフレームワークのコントローラ構造は、コントローラという抽象クラスに定義されています.コントローラを作成したい場合は、まずクラスを作成し、抽象クラスコントローラから継承する必要があります.UMLクラス図は次のとおりです.
007.ASP.NET MVC控制器依赖注入_第1张图片
すべてのコントローラにはルートインタフェースIControllerがあり、抽象クラスControllerBaseはそれから自分の方法を実現します.もう1つの抽象クラスはControllerBaseから継承されます.このクラスはControllerで、すべてのカスタムコントローラクラスがControllerから継承されるか、そのサブクラスから継承されます.
四.簡単なカスタムコントローラ
MVCプロジェクトを作成すると、AccountControllerとHomeControllerの2つのコントローラが得られます.
007.ASP.NET MVC控制器依赖注入_第2张图片
007.ASP.NET MVC控制器依赖注入_第3张图片
HomeControllerのコード実装を見に行くと、独自の構築方法がないことがわかります.
 1 public class HomeController : Controller  2 {  3     public ActionResult Index()  4  {  5         ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";  6         return View();  7  }  8     public ActionResult About()  9  { 10         ViewBag.Message = "Your app description page."; 11         return View(); 12  } 13 } 

ここには構造方法がないことはよく知られていますが、コンパイル時にパラメータのない構造方法が作成されます.
1 ublic class HomeController : Controller 2 { 3     public HomeController() 4  { 5  } 6 } 

次にILoggerインタフェースとその実装クラスDefaultLoggerクラスを作成します.HomeコントローラはILoggerタイプのオブジェクトをパラメータとして使用し、そのコントローラ構築方法に注入します.
 1 public interface ILogger  2 {  3     void Log(string logData);  4 }  5 public class DefaultLogger : ILogger  6 {  7     public void Log(string logData)  8  {  9         System.Diagnostics.Debug.WriteLine(logData, "default"); 10  } 11 } 

ILogger付きホームコントローラの構成方法は以下の通りです.
1 public class HomeController : Controller 2 { 3     private readonly ILogger _logger; 4     public HomeController(ILogger logger) 5  { 6         _logger = logger; 7  } 8 } 

今までどこでDefaultLoggerオブジェクトをインスタンス化したのか、コントローラへの伝達方法も分かりませんでした.コード作成段階でプログラムはエラーを報告しませんが、コードを実行するとエラーが報告されます.以下のようにします.
007.ASP.NET MVC控制器依赖注入_第4张图片
上記のスレッドレコードを見ると、DefaultControllerActivvatorオブジェクトから例外MissingMethonExceptionが放出されます.MSDNに行って、この異常がどのように引き起こされたのかを探すと、適切な方法が見つからないことに気づきます.次の異常InvalidOperationExceptionを見てください.MissingMethodExceptionが含まれています.コントローラの構築方法にパラメータ付きの構築方法があることを確認するために、より役立つ情報が表示されます.コードを正常に動作させるには、パラメータ付きの構築方法が必要です.フレームワークは、コントローラオブジェクトが作成した構築方法を作成します.問題は、このコントローラにDefaultLoggerオブジェクトをどのように渡すかです.練習を続けてください.私たちは続けて下を見ます.
五.MVCフレームワークコントローラオブジェクトの作成方法
DefaultLoggerオブジェクトをHomeControllerに注入する前に、MVCフレームワークがコントローラオブジェクトをどのように作成するかという概念が必要です.IControllerFactoryインタフェースの主な責任は、コントローラオブジェクトの作成です.DefaultControllerFactoryは、フレームワークのデフォルトで提供される拡張可能なクラスです.無参の構造方法を追加し、ブレークポイントを設定すると、プログラムがこの時点でここにとどまることがわかります.
007.ASP.NET MVC控制器依赖注入_第5张图片
上記の画像を見ると、IControllerFactoryタイプのDefaultControllerFactoryオブジェクトが表示されます.DefaultControllerFactoryには、Create、GetControllerInstance、CreateControllerなどの方法があります.これらの方法では、HomeControllerオブジェクトが作成されます.MVCフレームワークはオープンソースです.より多くの方法を知りたい場合は、公式のリソースをダウンロードすることができます.自分で読む.デバッグのコードを見ると、DefaultControllerFactoryオブジェクトがCurrentControllerFactoryによって表示されます.
007.ASP.NET MVC控制器依赖注入_第6张图片
六.コントローラファクトリをカスタマイズする理由
デフォルトのコントローラファクトリでは、パラメータなしのコンストラクションメソッドを使用してコントローラオブジェクトを作成していることがわかります.私たちは自分のパラメータ付きコントローラの構造方法を注入することができます.
 1 public class HomeController : Controller  2 {  3     private readonly ILogger _logger;  4     public HomeController():this(new DefaultLogger())  5  {  6  }  7     public HomeController(ILogger logger)  8  {  9         _logger = logger; 10  } 11 }    

多くの開発者が上の依存注入について誤解していることを発見しました.それは依存注入の形式ではありません.これは確かにコンポーネントの原則に違反している.この原則の願いは、上層部のモジュールは低レベルのモジュールに依存することができず、双方は抽象層に依存し、細部は抽象層に体現しなければならない.上のコードでは、HomeControllerが独自のDefaultLoggerオブジェクトを作成しました.ILoggerインタフェースの拡張(DefaultLogger)に直接依存し、将来新しい拡張(ILoggerインタフェースを拡張)があれば、HomeControllerの方法を修正する必要があるので、適切な方法でコンポーネントを注入する必要があります.ILoggerコンポーネントを注入するには、パラメータ付きの構造方法を使用しますが、デフォルトのDefaultControllerFactoryではサポートされていないので、独自のコントローラファクトリを作成します.
七.カスタムコントローラファクトリ
私は2つの方法で自分のコントローラ工場を作成する方法を示します.
7.1経路1
IControllerFactoryインタフェースを拡張した新しいコントローラファクトリを作成できます.カスタムコントローラファクトリの名前は、次のようになります.
 1 public class CustomControllerFactory : IControllerFactory  2 {  3     public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)  4  {  5         ILogger logger = new DefaultLogger();  6         var controller = new HomeController(logger);  7         return controller;  8  }  9     public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior( 10        System.Web.Routing.RequestContext requestContext, string controllerName) 11  { 12         return SessionStateBehavior.Default; 13  } 14     public void ReleaseController(IController controller) 15  { 16         IDisposable disposable = controller as IDisposable; 17         if (disposable != null) 18  disposable.Dispose(); 19  } 20 } 

最初のステップでは、CustomControllerFactoryをMVCフレームワークに登録し、Application_スタートイベントにコードを書きます.
 1 public class MvcApplication : System.Web.HttpApplication  2 {  3     protected void Application_Start()  4  {  5  RegisterCustomControllerFactory ();  6  }  7 }  8 private void RegisterCustomControllerFactory ()  9 { 10     IControllerFactory factory = new CustomControllerFactory(); 11  ControllerBuilder.Current.SetControllerFactory(factory); 12 } 

プログラムを実行すると、その無パラメータの構造方法が実行されていないことがわかります.そのパラメータ付きの構造方法が実行されています.君の問題はこんなに簡単に解決した.
007.ASP.NET MVC控制器依赖注入_第7张图片
コントローラ工場を構築して反射メカニズムを使用することができます.
 1 public class CustomControllerFactory : IControllerFactory  2 {  3     private readonly string _controllerNamespace;  4     public CustomControllerFactory(string controllerNamespace)  5  {  6         _controllerNamespace = controllerNamespace;  7  }  8     public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)  9  { 10         ILogger logger = new DefaultLogger(); 11         Type controllerType = Type.GetType(string.Concat(_controllerNamespace, ".", controllerName, "Controller")); 12         IController controller = Activator.CreateInstance(controllerType, new[] { logger }) as Controller; 13         return controller; 14  } 15 } 

7.2経路2
ここではIControllerFactoryインタフェースを拡張するのではなく、DefaultControllerFactoryクラスを継承し、そのメソッドを変更します.もちろんコントローラファクトリもプログラム起動のイベントに注入します.コードは次のとおりです.
1 public class CustomControllerFactory : DefaultControllerFactory 2 { 3     protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType) 4  { 5         ILogger logger = new DefaultLogger(); 6         IController controller = Activator.CreateInstance(controllerType, new[] { logger }) as Controller; 7         return controller; 8  } 9 } 

(MEFを外してカスタムコントローラファクトリを作成する方法は、自分でもなかなか理解できないので、見ておきましょう).