こんにちは、サイオステクノロジー技術部 武井です。前回に引き続き、今回はいろんな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());

