こんにちは、サイオステクノロジー技術部 武井です。前回に引き続き、今回はいろんなDIの方法を書きます。
その1
以前ご紹介した方法は、以下のようにジェネリックの第1引数にインターフェース、第2引数にその実装クラスを指定しました。
AddSingleton<[インターフェースの型],[インターフェースの実装クラスの型]>();
以下のような書き方も可能みたいです。
AddSingleton<[クラスの型]>();
上記のクラスは、別に何らかのインターフェースを実装している必要はなく、普通のクラスでOKです。この場合、[クラスの型]をnewしたインスタンスがDIコンテナに登録され、スコープはSingletonになります。この書き方を実践したソースコードのサンプルは以下のとおりです。
public class Startup { public void ConfigureServices(IServiceCollection services) { // これはHelloWorldクラスのインスタンスをDIする記述です。 services.AddSingleton<HelloWorld>(); services.AddMvc(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } } public class HelloWorld { public string Greet() { return "こんにちは世界"; } } public class HomeController : Controller { private HelloWorld _helloWorld; // HelloWorldクラスをコンストラクタインジェクションしています。 // 「その1」ではインターフェースを定義していましたが、 // 今回はAddSingletonメソッドでクラスしか定義してないので、 // クラスを指定しています。当然このhelloWorldにはHelloWorldクラスを // newしたインスタンスが入っています。 public HomeController(HelloWorld helloWorld) { this._helloWorld = helloWorld; } public IActionResult Index() { this.ViewBag.Greet = this._helloWorld.Greet(); return View(); } }
ビュー(index.cshtml)は以下のとおりです。
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title></title> </head> <body> @this.ViewBag.Greet </body> </html>
実行結果は以下の通りとなります。
こんにちは世界
さくっと何かのクラスのインスタンスをDIしたいときにこういう記述が役に立つのだと思います。
その2
その1の記述は以下のように記載することも出来ます。
AddSingleton(Func<IServiceProvider, TService> implementationFactory)
先程の「こんにちは世界」のソースコードにて、HelloWorldをDIする部分を上記の書き方で実現するためには、以下のようになります。
services.AddSingleton(sp => { return new HelloWorld(); });
もっと省略した書き方は以下のようになります。
services.AddSingleton(_ => new HelloWorld());