学堂学堂学堂公众号手机端

手动获取IServiceProvider依赖注入的 服务实例

nianxian1年前 (2023-08-19)阅读数 146#科技
 手动获取IServiceProvider依赖注入的 服务实例
Task.Run(() => {
try
{
//Task里创建了新的IServiceScope
using var scope = _scopeFactory.CreateScope();
//通过IServiceScope创建具体实例
LibraryContext dbContext = scope.ServiceProvider.GetService<LibraryContext>();
var list = dbContext!.Informations.Where(i => i.IsDelete == 0).Take(100).ToList();
}
Task.Run(() => {
try
{
//Task里创建了新的IServiceScope
using var scope = _serviceProvider.CreateScope();
//通过IServiceScope创建具体实例
LibraryContext dbContext = scope.ServiceProvider.GetService<LibraryContext>();
var list = dbContext!.Informations.Where(i => i.IsDelete == 0).Take(100).ToList();
}
[Route("api/[controller]/[action]")]
[ApiController]
public class InformationController : ControllerBase
{
private readonly LibraryContext _libraryContext;
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<InformationController> _logger;
public InformationController(LibraryContext libraryContext, 
IServiceProvider serviceProvider,
ILogger<InformationController> logger)
{
_libraryContext = libraryContext;
_serviceProvider = serviceProvider;
_logger = logger;
}
[HttpGet]
public string GetFirst()
{
var caseInfo = _libraryContext.Informations.Where(i => i.IsDelete == 0).FirstOrDefault();
//这里直接使用了Task方式
Task.Run(() => {
try
{
//Task里创建了新的IServiceScope
using var scope = _serviceProvider.CreateScope();
//通过IServiceScope创建具体实例
LibraryContext dbContext = scope.ServiceProvider.GetService<LibraryContext>();
var list = dbContext!.Informations.Where(i => i.IsDelete == 0).Take(100).ToList();
}
catch (Exception ex)
{
_logger.LogError(ex.Message, ex);
}
});
return caseInfo.Title;
}
}
报错:
Cannot access a disposed object.
Object name: 'IServiceProvider'.
[Route("api/[controller]/[action]")]
[ApiController]
public class InformationController : ControllerBase
{
private readonly LibraryContext _libraryContext;
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger<InformationController> _logger;
public InformationController(LibraryContext libraryContext, 
IServiceScopeFactory scopeFactory,
ILogger<InformationController> logger)
{
_libraryContext = libraryContext;
_scopeFactory = scopeFactory;
_logger = logger;
}
[HttpGet]
public string GetFirst()
{
var caseInfo = _libraryContext.Informations.Where(i => i.IsDelete == 0).FirstOrDefault();
//这里直接使用了Task方式
Task.Run(() => {
try
{
//Task里创建了新的IServiceScope
using var scope = _scopeFactory.CreateScope();
//通过IServiceScope创建具体实例
LibraryContext dbContext = scope.ServiceProvider.GetService<LibraryContext>();
var list = dbContext!.Informations.Where(i => i.IsDelete == 0).Take(100).ToList();
}
catch (Exception ex)
{
_logger.LogError(ex.Message, ex);
}
});
return caseInfo.Title;
}
}
//如果想获取根容器的实例则可以通过获取IServiceScopeFactory实例获取,最后请注意IServiceScope的释放问题。
微软给我们的建议是
注入一个IServiceScopeFactory以便在后台工作项中创建一个范围。
IServiceScopeFactory是一个单例对象。
在后台线程中创建一个新的依赖注入范围。
不引用控制器中的任何东西。
不从传入请求中捕获DbContext。
https://learn.microsoft.com/en-us/aspnet/core/performance/performance-best-practices?view=aspnetcore-6.0#do-not-capture-services-injected-into-the-controllers-on-background-threads
[HttpGet("/fire-and-forget-3")]
public IActionResult FireAndForget3([FromServices]IServiceScopeFactory serviceScopeFactory)
{
_ = Task.Run(async () =>
{
await Task.Delay(1000);
using (var scope = serviceScopeFactory.CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ContosoDbContext>();
context.Contoso.Add(new Contoso());
await context.SaveChangesAsync();                                        
}
});
return Accepted();
}
public void Configure(IApplicationBuilder app)
{
ServiceLocator.Instance = app.ApplicationServices;
}
public static class ServiceLocator
{
public static IServiceProvider Instance { get; set; }
}
public void DemoMethod()
{
var demoService = ServiceLocator.Instance.GetService<IDemoService>();
}
注意:使用ServiceLocator.Instance.GetService()只能获取AddTransient和AddSingleton注入的对象,而不能获取AddScoped(请求生命周期内唯一)注入的对象,因为获取的对象和构造函数获取的不是同一个(即获取的对象没有共享),使用场景比如IUnitOfWork。
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
namespace Domain
{
public class DemoService : IDemoService
{
private IUnitOfWork _unitOfWork;
public DemoService (IHttpContextAccessor httpContextAccessor)
{
_unitOfWork = httpContextAccessor.HttpContext.RequestServices.GetService<IUnitOfWork>();
}
}
}
https://www.cnblogs.com/donchen/p/16484705.html

源文:https://www.cnblogs.com/wucy/p/16566495.html
private readonly IServiceProvider _serviceProvider;
public SomeService(IServiceProvider serviceProvider) {
_serviceProvider = serviceProvider;
}
var eventBus = _serviceProvider.GetService(typeof(IEventBus)) as IEventBus;
https://www.codenong.com/50411466/

此随笔或为自己所写、或为转载于网络。仅用于个人收集及备忘。

版权声明

本文仅代表作者观点,不代表xx立场。
本文系作者授权xx发表,未经许可,不得转载。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门