[解決済み] ConfigureServices内からASP.NET Core DIでインスタンスを解決する
質問
ASP.NET Core MVC 内蔵の依存性注入フレームワークを使用して、手動で型を解決するにはどうすればよいですか?
コンテナのセットアップは簡単です。
public void ConfigureServices(IServiceCollection services)
{
// ...
services.AddTransient<ISomeService, SomeConcreteService>();
}
しかし、どのようにすれば
ISomeService
インジェクションを実行せずに? 例えば、こんなことをしたいのです。
ISomeService service = services.Resolve<ISomeService>();
にはそのようなメソッドはありません。
IServiceCollection
.
解決方法は?
その
IServiceCollection
インタフェースは
構築
依存性注入コンテナです。完全に構築された後、それは
IServiceProvider
インスタンスを作成し、それを使ってサービスを解決することができます。このインスタンスはサービスを解決するために使用できます。
IServiceProvider
をどのようなクラスにも適用できます。そのため
IApplicationBuilder
と
HttpContext
クラスは、サービスプロバイダも提供することができます。
ApplicationServices
または
RequestServices
プロパティをそれぞれ指定します。
IServiceProvider
を定義しています。
GetService(Type type)
メソッドでサービスを解決します。
var service = (IFooService)serviceProvider.GetService(typeof(IFooService));
また、次のような便利な拡張メソッドも用意されています。
serviceProvider.GetService<IFooService>()
(を追加)。
using
に対して
Microsoft.Extensions.DependencyInjection
).
スタートアップ・クラス内のサービスの解決
依存関係の注入
ランタイムのホスティングサービスプロバイダは、特定のサービスを
Startup
クラスのような
IConfiguration
,
IWebHostEnvironment
(
IHostingEnvironment
3.0より前のバージョンでは)。
ILoggerFactory
と
IServiceProvider
. 後者はホスティング層によって構築されたインスタンスであることに注意してください。
には、アプリケーションを起動するために必要なサービスだけが含まれています。
.
は
ConfigureServices()
メソッドはサービスを注入することはできません。
IServiceCollection
引数で指定します。これは、以下の理由で理にかなっています。
ConfigureServices()
は、アプリケーションで必要なサービスを登録する場所です。しかし、例えばスタートアップのコンストラクタに注入されたサービスをここで使用することもできます。
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// Use Configuration here
}
に登録されているサービスは、すべて
ConfigureServices()
に注入することができます。
Configure()
メソッドの後に、任意の数のサービスを追加することができます。
IApplicationBuilder
パラメータを使用します。
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IFooService>();
}
public void Configure(IApplicationBuilder app, IFooService fooService)
{
fooService.Bar();
}
依存関係を手動で解決する
サービスを手動で解決する必要がある場合、できれば
ApplicationServices
が提供する
IApplicationBuilder
の中で
Configure()
メソッドを使用します。
public void Configure(IApplicationBuilder app)
{
var serviceProvider = app.ApplicationServices;
var hostingEnv = serviceProvider.GetService<IHostingEnvironment>();
}
を渡して直接使用することが可能です。
IServiceProvider
のコンストラクタで使用します。
Startup
というクラスがありますが、上記のように
これには、サービスの限定されたサブセットが含まれます。
そのため、有用性は限定的である。
public Startup(IServiceProvider serviceProvider)
{
var hostingEnv = serviceProvider.GetService<IWebHostEnvironment>();
}
でサービスを解決する必要がある場合は
ConfigureServices()
メソッドを使用する場合は、別のアプローチが必要です。中間的な
IServiceProvider
から
IServiceCollection
登録されたサービスを含むインスタンス
それまで
:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IFooService, FooService>();
// Build the intermediate service provider
var sp = services.BuildServiceProvider();
// This will succeed.
var fooService = sp.GetService<IFooService>();
// This will fail (return null), as IBarService hasn't been registered yet.
var barService = sp.GetService<IBarService>();
}
ご注意ください。
一般に、サービスを
ConfigureServices()
メソッドで使用されます。
コンフィギュレーション
アプリケーション・サービスです。へのアクセスだけが必要な場合もあります。
IOptions<MyOptions>
のインスタンスです。の値をバインドすることで、これを実現することができます。
IConfiguration
のインスタンスに
MyOptions
(これは本質的にオプションフレームワークが行うことです)。
public void ConfigureServices(IServiceCollection services)
{
var myOptions = new MyOptions();
Configuration.GetSection("SomeSection").Bind(myOptions);
}
のオーバーロードを使用することもできます。
AddSingleton/AddScoped/AddTransient
:
// Works for AddScoped and AddTransient as well
services.AddSingleton<IBarService>(sp =>
{
var fooService = sp.GetRequiredService<IFooService>();
return new BarService(fooService);
}
サービスを手動で解決する(別名:サービスロケータ)ことは 一般にアンチパターンと呼ばれる . フレームワークやインフラ層での使用例はありますが、できる限り避けるべきです。
関連
-
[解決済み】エラー。「戻り値を変更できません」 C#
-
[解決済み】"出力タイプがクラスライブラリのプロジェクトは直接起動できない"
-
[解決済み】C#で四捨五入する方法
-
[解決済み】ASP.NET Core Dependency Injectionのエラーです。アクティブ化しようとしているときに、タイプのサービスを解決できません。
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】aspNetCore 2.2.0 - AspNetCoreModuleV2 エラー
-
[解決済み】ファイルやアセンブリ、またはその依存関係の1つをロードできませんでした。
-
[解決済み] ASP.NET CoreでカスタムのAuthorizeAttributeを作成する方法は?
-
[解決済み] コントローラから特定のステータスコードと内容を返すには?
-
[解決済み] ConfigureServices内部でIOptionsインスタンスを解決する方法は?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】スクリプトクラスが見つからないので、スクリプトコンポーネントを追加できない?
-
[解決済み】Unity3DでOnTriggerEnterが動作しない件
-
[解決済み】Visual studio 2019がデバッグ時にフリーズする件
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み】ランダムなブーリアンを生成する最速の方法
-
[解決済み】インデックスが範囲外でした。コレクションパラメータname:indexのサイズより小さく、非負でなければなりません。
-
[解決済み】IntPtrとは一体何なのか?
-
[解決済み】ファイルやアセンブリ、またはその依存関係の1つをロードできませんでした。
-
VSでscanfエラーを恒久的に解決するには、ソースファイルを作成し、自動的に#define _CRT_SECURE_NO_WARNINGS 1を追加してください。
-
[解決済み] ConfigureServices内部でIOptionsインスタンスを解決する方法は?