.net core依赖注入是否支持Lazy<T>

Does .net core dependency injection support Lazy<T>

我正在尝试使用通用 Lazy class 来实例化具有 .net 核心依赖项注入扩展的昂贵 class。我已经注册了 IRepo 类型,但我不确定 Lazy class 的注册会是什么样子,或者它是否受支持。作为解决方法,我使用了这种方法 http://mark-dot-net.blogspot.com/2009/08/lazy-loading-of-dependencies-in-unity.html

配置:

public void ConfigureService(IServiceCollection services)
{
    services.AddTransient<IRepo, Repo>();
    //register lazy
}

控制器:

public class ValuesController : Controller 
{
    private Lazy<IRepo> _repo;

    public ValuesController (Lazy<IRepo> repo)
    {
        _repo = repo;
    }

    [HttpGet()]
    public IActionResult Get()
    {
         //Do something cheap
         if(something)
             return Ok(something);
         else
             return Ok(repo.Value.Get());
    }
}

您只需要为创建 Lazy<IRepo> 对象的工厂方法添加注册。

public void ConfigureService(IServiceCollection services)
{
    services.AddTransient<IRepo, Repo>();
    services.AddTransient<Lazy<IRepo>>(provider => new Lazy<IRepo>(provider.GetService<IRepo>));
}

这是另一种支持 Lazy<T> 通用注册的方法,这样任何类型都可以延迟解析。

services.AddTransient(typeof(Lazy<>), typeof(Lazier<>));

internal class Lazier<T> : Lazy<T> where T : class
{
    public Lazier(IServiceProvider provider)
        : base(() => provider.GetRequiredService<T>())
    {
    }
}

要在Lazy中获取的服务将通过工厂注册方法重新引入预期服务类型的新 Lazy 并使用 serviceProvider.GetRequiredService.

为其实现提供
services.AddTransient<IRepo, Repo>()
        .AddTransient(serviceProvider => new Lazy<IRepo>(() => serviceProvider.GetRequiredService<IRepo>()));

在我看来,下面的代码应该可以完成工作(.net core 3.1)

services.AddTransient<IRepo, Repo>();
services.AddTransient(typeof(Lazy<>), typeof(Lazy<>));

将服务注册为懒惰

services.AddScoped<Lazy<AService>>();
services.AddScoped<Lazy<BService>>();

或者通过创建扩展程序

static class LazyServiceCollection
{
    public static void AddLazyScoped<T>(this IServiceCollection services)
    {
        services.AddScoped<Lazy<T>>();
    }
}

...

services.AddLazyScoped<AService>();
services.AddLazyScoped<BService>();

并使用它

[ApiController, Route("lazy")]
public class LazyController : ControllerBase
{
    private readonly Lazy<AService> _aService;
    private readonly Lazy<BService> _bService;

    public LazyController(Lazy<AService> aService, Lazy<BService> bService)
    {
        _aService = aService;
        _bService = bService;
    }

    [HttpGet("a")]
    public ActionResult GetA()
    {
        _aService.Value.DoWork();
        return new OkResult();
    }

    [HttpGet("b")]
    public ActionResult GetB()
    {
        _bService.Value.DoWork();
        return new OkResult();
    }
}

结果

Init AService
AService Work