-
Notifications
You must be signed in to change notification settings - Fork 0
MS_ASPNETCoreDI
※ 詳しくはコチラを参照。
-
ConfigureServices メソッドでの登録メソッドによりライフサイクルが変わってくる。
- AddSingleton : アプリケーションにて共有のシングルトンインスタンスを作成する。
- AddScoped : Web リクエストごとに新しいインスタンスを作成する。
- AddTransient : Dependency が要求されるごとに新しいインスタンスを作成する。
-
Configure メソッドには、ConfigureServices メソッドで登録したサービスが、
IApplicationBuilder や引数を経由で渡されるので、これを使用して構成する。
移行メモ(誤記): 原文の「AddSigleton」は
AddSingletonの誤記と判断し修正した。
補足(
Startup.csは無くなった/最新化): 本節が前提とする
**Startupクラス(ConfigureServices/Configure)**は、
.NET 6 の最小ホスティング モデルにより、既定では生成されなくなった。
〜.NET 5 .NET 6 以降 構成の場所 Startup.csの 2 メソッドProgram.csの 1 ファイルサービス登録 ConfigureServices(IServiceCollection)builder.Services.Add~パイプライン Configure(IApplicationBuilder, ...)app.Use~// .NET 6 以降(Program.cs のみ) var builder = WebApplication.CreateBuilder(args); // ← 旧 ConfigureServices に相当 builder.Services.AddControllersWithViews(); builder.Services.AddScoped<IOrderRepository, SqlOrderRepository>(); var app = builder.Build(); // ← 旧 Configure に相当 app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
Startupを使い続けることも可能
(builder.Servicesに手で渡す形にすれば動く)だが、
新規テンプレートは生成しない。
移行の詳細は ASP.NET Coreへの移行 を参照。ライフタイムの意味は変わっていないので、
本節の 3 つの説明は現在もそのまま有効である
(選択の指針と事故例は DI の「コンテナー」節を参照)。
-
Constructor インジェクション
MVC の Controller は、constructor を使用しサービスを挿入する。 -
Action インジェクション
Action method のパラメタとしてサービスを挿入することもできる。 -
参考
補足(使い分け): 2 つの注入方法は、使う頻度で選ぶ。
方法 書き方 適する場面 Constructor public HomeController(IFoo foo)多くのアクションで使う Action( [FromServices])Index([FromServices] IFoo foo)1 つのアクションでしか使わない(重いサービス等) public sealed class OrderController(IOrderService svc) : Controller { // 全アクションで使うものは constructor public IActionResult Index() => View(svc.List()); // ここでしか使わない重いものは Action 注入 public IActionResult Report([FromServices] IReportGenerator gen) => File(gen.Build(), "application/pdf"); }.NET 7 以降では
[FromServices]の省略が可能になった
(登録済みの型なら、属性なしでも DI から解決される)。
ただし明示した方が読み手に意図が伝わるため、
属性を付ける運用でも問題ない。なお、Minimal API でも同じ仕組みが働く。
app.MapGet("/orders", (IOrderService svc) => svc.List());
-
View インジェクション
- @inject [サービスの型] [変数名]
- Model プロパティ風(@model ViewModel のクラス型)
に書く。
補足(使いどころは限定する):
@injectは便利だが、
ビューにロジックを持ち込む入口にもなる。@inject IStringLocalizer<HomeController> L @inject IOptions<SiteOptions> Options <h1>@L["Welcome"]</h1> <p>@Options.Value.SiteName</p>適切な用途:
- ローカライズ(
IStringLocalizer、IViewLocalizer)- 設定値の参照(
IOptions<T>)- 表示専用のヘルパー(
IHtmlLocalizer等)避けるべき用途:
- リポジトリや
DbContextを注入してビューから DB を引く
(N+1 クエリ、例外処理の欠落、テスト不能)表示に必要なデータは、コントローラーで揃えて ViewModel に載せるのが原則。
@injectは「ビュー自身の関心事」に限って使う。
ASP.NET Core では、
- 既定では、Microsoft.Extensions.DependencyInjection を使用する。
- ConfigureServices メソッドが、IServiceProvider を返すようにシグネチャを変更する方法で、
Autofac (Autofac.Extensions.DependencyInjection) など、
別のコンテナに切替可能らしい。
補足(現在の差し替え方/最新化): 原文が述べる
「ConfigureServicesがIServiceProviderを返す」方式は
ASP.NET Core 2.x 時代のもので、
.NET Core 3.0 以降は非対応になった
(スコープ検証が働かない等の問題があったため)。現在は
UseServiceProviderFactoryを使う。var builder = WebApplication.CreateBuilder(args); // 標準の登録はそのまま書ける builder.Services.AddControllers(); // コンテナーを Autofac に差し替える builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory()); builder.Host.ConfigureContainer<ContainerBuilder>(cb => { cb.RegisterModule<MyModule>(); // Autofac 固有の登録 cb.RegisterType<Foo>().As<IFoo>().PropertiesAutowired(); });要点:
IServiceCollectionへの登録は標準の作法のままでよく、
固有機能が必要な部分だけをConfigureContainerに書く。
このため、まず標準で始めて、後から差し替えるという順序が取れる。差し替える動機(標準に無い機能)は
.NET Core における DI の表を参照。
なお .NET 8 のキー付きサービスにより、
「名前で使い分けたい」という代表的な動機は標準で満たせるようになった。
-
ASP.NET Core での依存関係の挿入
https://learn.microsoft.com/ja-jp/aspnet/core/fundamentals/dependency-injection -
ASP.NET Core でのアプリケーションのスタートアップ
https://learn.microsoft.com/ja-jp/aspnet/core/fundamentals/startup -
ASP.NET Core の最小 API
https://learn.microsoft.com/ja-jp/aspnet/core/fundamentals/minimal-apis
-
.NET 系の DI コンテナ
https://qiita.com/okazuki/items/239ca5ef46e5a085e085 -
DI (依存性注入) って何のためにするの
かわからない人向けに頑張って説明してみる
https://qiita.com/okazuki/items/a0f2fb0a63ca88340ff6 -
DI って何でするのかわからない人向けに
頑張って説明してみる「本来の意味」
https://qiita.com/okazuki/items/0c17a161a921847cd080 -
DI コンテナは自分で new しないでフレームワークを探そう
https://qiita.com/okazuki/items/6327d05fd84fd5de3299 -
DIコンテナのテスト以外での利点について (7/15修正)
https://qiita.com/crexista/items/606976d941728a90b42b -
「DIコンテナのテスト以外での利点について」の自分の感想
https://qiita.com/okazuki/items/a470e05c1a263921a59c
ASP.NET Core MVC のDIコンテナを利用する
- Part.0(準備編)
http://mrgchr.hatenablog.com/entry/2016/10/21/000000 - Part.1
http://mrgchr.hatenablog.com/entry/2016/10/22/000000 - Part.2
http://mrgchr.hatenablog.com/entry/2016/10/23/000000
-
AutofacというDIコンテナを触ってみた - かずきのBlog@hatena
http://blog.okazuki.jp/entry/2014/02/26/232829 -
Qiita
-
Autofac について調べてみた
- その1 インスタンスのスコープ
https://qiita.com/TsuyoshiUshio@github/items/f4d83c76520a86c028dc - その2 インスタンスのスコープ補足
https://qiita.com/TsuyoshiUshio@github/items/066e6feae4b4f7c1e0b8 - その3 WebApi とのインテグレーション
https://qiita.com/TsuyoshiUshio@github/items/f4d83c76520a86c028dc
- その1 インスタンスのスコープ
-
ASP.NET Coreアプリの
Dependency Injection処理を別のDIコンテナに委譲する(完全版)
https://qiita.com/yamaokunousausa/items/bc81d8498ecf62da0208 -
ASP.NET CoreでIServiceProviderに登録される情報を確認する
https://qiita.com/yamaokunousausa/items/0d5450ff6b50ebe7129e -
ASP.NET Coreで設定ファイルによるDIの設定を行い
環境によって使用されるコンポーネントを変更する
https://qiita.com/yamaokunousausa/items/bd5ee2d0af79aa55923d
-
Tags: 移行, プログラミング, .NET開発, .NET Core, ASP.NET, ASP.NET MVC
このWikiは「Open棟梁Project」,「OSSコンソーシアム 開発基盤部会」によって運営されています。