- Published on
ASP.NET Core 如何使用內建的 DI 注入多個實作
模擬多個實作
下面我們使用 Log 寫入的不同來模擬多個實作
public interface ILog
{
void Info(string msg);
}
public class FileLog : ILog
{
public void Info(string msg)
{
Console.WriteLine($"FileLog - {msg}");
}
}
public class SentryLog : ILog
{
public void Info(string msg)
{
Console.WriteLine($"SentryLog - {msg}");
}
}
註冊
在 Startup 的 ConfigureServices 註冊兩個 Log
services.AddScoped<ILog, FileLog>();
services.AddScoped<ILog, SentryLog>();
使用單一 ILog
在 controller 裡面注入 ILog
private readonly ILog _log;
public HomeController(ILog log)
{
_log = log;
}
public IActionResult Index()
{
_log.Info("TEST");
return Ok("OK");
}
直接執行程式,會發現 ILog 跑的是 SentryLog
在注入多個實作的時候,預設是拿到最後註冊的那一個
使用多個 ILog
把前面注入 ILog
換成 IEnumerable<ILog>
,然後變成 foreach
寫入 Log
private readonly IEnumerable<ILog> _logs;
public HomeController(IEnumerable<ILog> logs)
{
_logs = logs;
}
public IActionResult Index()
{
foreach (var log in _logs)
{
log.Info("TEST");
}
return Ok("OK");
}
執行程式,ILog 會寫入 FileLog 和 SentryLog
這裡要注意的是注入的型別一定要是
IEnumerable<>
,如果使用List<>
是會出錯的
動態使用 ILog
如果要動態注入不同的實體,可以變向的使用判斷的方式來做到動態注入的效果,判斷的來源可以來自 appsetting 或是 database 都可以
當然這個判斷可以寫成 extension method 會比較方便使用
private readonly IEnumerable<ILog> _logs;
public HomeController(IEnumerable<ILog> logs)
{
_logs = logs;
}
public IActionResult Index()
{
var log = _logs.FirstOrDefault(a => a.GetType().Name == "FileLog");
log?.Info("TEST");
return Ok("OK");
}
執行結果