假設我有一個Service是在DI容器為Singleton,而該Service依賴DBContext,
之後該Service會定期創建一個新物件 - Connection
新的物件又會需要DBContext進行DB讀寫及LogService, 我如何將該兩樣傳入到Connection中?
Class BackgroundService
{
List<Connection> Connections;
public BackgroundService(DBContext dbcontext);
public void Timeout()
{
Connections.Add(new Connection("192.168.0.100", ?, ?));
}
}
Class Connection
{
public Connection(string ipAddress, DBContext dbcontext, ILogService logService);
}
假設DBContext 是使用預設的Scoped,如果在BackgroundService(Singleton)注入Scoped時就會報錯,且不知道您要如何使用Connections,如果是我會有兩種做法:
public class BackgroundService
{
private readonly List<Connection> Connections;
public BackgroundService()
{
Connections = new List<Connection>();
}
public void Timeout()
{
Connections.Add(new Connection("192.168.0.100"));
}
public void AllConnectionsDoSomething(DBContext dbcontext, ILogService logService)
{
foreach (var connection in Connections)
{
connection.DoSomething(dbcontext, logService);
}
}
}
public class Connection
{
private readonly string ipAddress;
public Connection(string ipAddress)
{
this.ipAddress = ipAddress;
}
public void DoSomething(DBContext dbcontext, ILogService logService)
{
//....
}
}
public class SampleController : Controller
{
private readonly DBContext dbcontext;
private readonly ILogService logService;
private readonly BackgroundService backgroundService;
public SampleController(DBContext dbcontext, ILogService logService, BackgroundService backgroundService)
{
this.dbcontext = dbcontext;
this.logService = logService;
this.backgroundService = backgroundService;
}
public IActionResult SampleAction()
{
backgroundService.AllConnectionsDoSomething(dbcontext, logService);
return Ok();
}
}
public class BackgroundService
{
private readonly List<Connection> Connections;
private readonly IServiceProvider serviceProvider;
public BackgroundService(IServiceProvider serviceProvider)
{
Connections = new List<Connection>();
this.serviceProvider = serviceProvider;
}
public void Timeout()
{
Connections.Add(new Connection("192.168.0.100", serviceProvider));
}
}
public class Connection
{
private readonly string ipAddress;
private readonly IServiceProvider _serviceProvider;
public Connection(string ipAddress, IServiceProvider serviceProvider)
{
this.ipAddress = ipAddress;
this._serviceProvider = serviceProvider;
}
public void DoSomething()
{
var scopeFactory = _serviceProvider.GetRequiredService<IServiceScopeFactory>();
using (var scope = scopeFactory.CreateScope())
{
var serviceProvider = scope.ServiceProvider;
var dbContext = serviceProvider.GetRequiredService<DBContext>();
var logService = serviceProvider.GetRequiredService<ILogService>();
//....
}
}
}
看不太懂,不是就傳進去嗎
Class BackgroundService
{
private readonly DBContext _dbcontext;
List<Connection> Connections;
public BackgroundService(DBContext dbcontext)
{
_dbcontext = dbcontext
}
public void Timeout()
{
Connections.Add(new Connection("192.168.0.100", _dbcontext, ?));
}
}
Class Connection
{
public DBContext mydbcontext {get;set;}
public Connection(string ipAddress, DBContext dbcontext, ILogService logService)
{
mydbcontext = dbcontext ;
}
}
//// todo
public void readdb(){
var data = thisconnection.mydbcontext.whattodo();
}
可以使用 IServiceProvider 取得 DI 物件。
public class BackgroundService
{
private List<Connection> Connections;
private readonly IServiceProvider _serviceProvider;
public BackgroundService(
IServiceProvider serviceProvider,
DBContext dbcontext)
{
_serviceProvider = serviceProvider;
}
public void Timeout()
{
Connections.Add(new Connection("192.168.0.100",
_serviceProvider.GetRequiredService<DBContext>(),
_serviceProvider.GetRequiredService<ILogService>()));
}
}