ASP.NET Core MVCコントローラ作成と依存注入
6789 ワード
私の最後のASPについてNET Coreリリース
この記事では、ASPについてご紹介します.NET Core MVCの
ASP.NET Coreでは、MVCミドルウェアがリクエストを受信すると、実行するコントローラと操作方法をルーティングで選択します.実際に動作するためには、MVCミドルウェアは、選択したコントローラのインスタンスを作成する必要があります.
コントローラを作成するプロセスは、多くの異なるプロバイダおよびファクトリクラスに依存するが、最終的には
ご覧のように、
周知の通り、ASP.NET Coreは、TypeActivatvatorCacheによってコントローラを作成する
重要な点は、
この動作を実証するために,単一のサービスとコントローラを含む簡単なMVCアプリケーションを作成した.サービスインスタンスには、関数を構築することによって設定されるnameプロパティがあります.デフォルトでは、
アプリケーションでは、
アプリケーションを実行すると、どのような結果が得られますか?
この
これは、コントローラを
ほとんどの場合、
幸いなことに、MVCフレームワークはこのような
ご覧のように、
アプリケーションにMVCサービスを追加する場合は、
上のコードで、ホームページをクリックするとDIコンテナでコントローラが作成されます.
もっと複雑なことをする必要がある場合は、いつでも自分の
デフォルトでは、ASP.NET Core MVCでは コントローラをDIコンテナから直接ロードする代わりに、
IDsiposable
オブジェクトの文書(中国語、英語原文)では、Mark RendleはMVCコントローラがリクエスト終了時にもリソースをリリースすると指摘している.一見、この範囲内のリソースがリクエスト終了時に解放されるのは明らかであるようだが、MVCコントローラの処理方式は実際には多くのサービスとは少し異なる.この記事では、ASPについてご紹介します.NET Core MVCの
IControllerActivator
がコントローラをどのように作成したのか、および依存注入によってコントローラを作成したのかの違い.デフォルトのIControllerActivator
ASP.NET Coreでは、MVCミドルウェアがリクエストを受信すると、実行するコントローラと操作方法をルーティングで選択します.実際に動作するためには、MVCミドルウェアは、選択したコントローラのインスタンスを作成する必要があります.
コントローラを作成するプロセスは、多くの異なるプロバイダおよびファクトリクラスに依存するが、最終的には
IControllerActivator
インタフェースを実装するインスタンスによって決定される.実装クラスには2つの方法しか必要ありません.public interface IControllerActivator { object Create(ControllerContext context); void Release(ControllerContext context, object controller);
}
ご覧のように、
IControllerActivator.Create
メソッドは、コントローラを作成するためのControllerContext
のインスタンスを渡します.コントローラの作成方法は、特定のインプリメンテーションに依存します.周知の通り、ASP.NET Coreは、TypeActivatvatorCacheによってコントローラを作成する
DefaultControllerActivator
を使用しています.TypeActivatorCache
クラスのコンストラクション関数を呼び出し、DIコンテナからコンストラクション関数に必要なパラメータの例を解析しようとする.重要な点は、
DefaultControllerActivator
は、コントローラのインスタンスをDIコンテナから解析しようとせず、コントローラの依存項目のみを解析することです.DefaultControllerActivatvatorの例
この動作を実証するために,単一のサービスとコントローラを含む簡単なMVCアプリケーションを作成した.サービスインスタンスには、関数を構築することによって設定されるnameプロパティがあります.デフォルトでは、
"default"
がデフォルトとして使用されます.public class TestService { public TestService(string name = "default") {
Name = name;
} public string Name { get; }
}
アプリケーションでは、
HomeController
はTestService
に依存し、Name
のプロパティの値を返します.public class HomeController : Controller { private readonly TestService _testService; public HomeController(TestService testService) {
_testService = testService;
} public string Index() { return "TestService.Name: " + _testService.Name;
}
}
Startup
ファイルにもう1つのコードがあります.ここで私はTestService
をDI容器に登録して範囲内のサービスとして、MVCミドルウェアとサービスを設定します.public class Startup { public void ConfigureServices(IServiceCollection services) {
services.AddMvc();
services.AddScoped();
services.AddTransient(ctx => new HomeController(new TestService("Non-default value")));
} public void Configure(IApplicationBuilder app) {
app.UseMvcWithDefaultRoute();
}
}
HomeController
のインスタンスを作成するためのファクトリメソッドを定義したことに気づきます.HomeController
タイプがDIコンテナに登録され、TestService
インスタンスにおいてカスタムName
属性が渡される.アプリケーションを実行すると、どのような結果が得られますか?
この
TestService.Name
プロパティはデフォルト値を使用しており、TestService
インスタンスがDIコンテナから直接取得されたことを示しており、HomeController
を作成するファクトリメソッドは直接無視されています.これは、コントローラを
DefaultControllerActivator
で作成した場合、DIコンテナからHomeController
インスタンスは作成されず、コンストラクション関数の依存性のみが解析されることを容易に理解できます.ほとんどの場合、
DefaultControllerActivator
を使用するのは良い選択ですが、遮断器や装飾器などの機能を持つサードパーティ製コンテナを使用するなど、DIコンテナを直接使用してコントローラを作成したい場合があります.幸いなことに、MVCフレームワークはこのような
IControllerActivator
実装を含み、それを有効にするために非常に便利な拡張方法を提供している.ServiceBasedControllerActivator
ご覧のように、
DefaultControllerActivator
はTypeActivatorCache
を使用してコントローラを作成します.MVCには、DIコンテナから直接コントローラを取得するServiceBasedControllerActivator
と呼ばれる別のインプリメンテーションも含まれています.その実現は非常に簡単です.public class ServiceBasedControllerActivator : IControllerActivator { public object Create(ControllerContext actionContext) { var controllerType = actionContext.ActionDescriptor.ControllerTypeInfo.AsType(); return actionContext.HttpContext.RequestServices.GetRequiredService(controllerType);
} public virtual void Release(ControllerContext context, object controller) {
}
}
アプリケーションにMVCサービスを追加する場合は、
AddControllersAsServices()
拡張メソッドを使用してDIベースのアクターを構成できます.public class Startup { public void ConfigureServices(IServiceCollection services) {
services.AddMvc()
.AddControllersAsServices();
services.AddScoped();
services.AddTransient(ctx => new HomeController(new TestService("Non-default value")));
} public void Configure(IApplicationBuilder app) {
app.UseMvcWithDefaultRoute();
}
}
上のコードで、ホームページをクリックするとDIコンテナでコントローラが作成されます.
HomeController
を作成するファクトリメソッドを登録したため、カスタムTestService
の構成は保持され、置き換えられたName
のプロパティを使用します.AddControllersAsServices
メソッドは、アプリケーション内のすべてのコントローラをDIコンテナに登録し(登録されていない場合)、IControllerActivator
をServiceBasedControllerActivator
に登録します.public static IMvcBuilder AddControllersAsServices(this IMvcBuilder builder)
{ var feature = new ControllerFeature();
builder.PartManager.PopulateFeature(feature); foreach (var controller in feature.Controllers.Select(c => c.AsType()))
{
builder.Services.TryAddTransient(controller, controller);
}
builder.Services.Replace(ServiceDescriptor.Transient()); return builder;
}
もっと複雑なことをする必要がある場合は、いつでも自分の
IControllerActivator
を実現することができます.しかし、私は何の理由も見つかりません.この2つの実現はまだあなたのニーズを満たすことができません.まとめ
IControllerActivator
がDefaultControllerActivator
に構成されている.DefaultControllerActivator
コントローラを作成するには、TypeActivatorCache
を使用します.DIコンテナからコンストラクション関数に必要なパラメータをロードして、コントローラのインスタンスを作成します.ServiceBasedControllerActivator
を使用することもできます.Startup.ConfigureServices
メソッドでは、MvcBuilder
のAddControllersAsServices()
拡張メソッドを使用して、このアクティブ化メソッドを構成できます.