.net核心依赖注入是否支持Lazy

问题描述 投票:15回答:3

我试图使用通用的Lazy类来实例化.net核心依赖注入扩展的昂贵类。我已经注册了IRepo类型,但是我不确定Lazy类的注册是什么样的,或者是否支持它。作为一种解决方法,我使用了这种方法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());
    }
}
c# dependency-injection asp.net-core .net-core lazy-initialization
3个回答
28
投票

这是另一种支持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>())
    {
    }
}

9
投票

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

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

-1
投票

我今天在我的部分代码中使用了上面的Lazier技术,但是当我想使用时,我发现我必须将其删除

IEnumerable<Lazy<ISomething>> 

注册:

services.AddLazier();
services.AddTransient<ISomething, SomeThing1>();
services.AddTransient<ISomething, SomeThing2>();

注射:

public class IndexModel : PageModel
{
    private IEnumerable<ISomething> _someThings;
    private IEnumerable<Lazy<ISomething>> _someLazyThings;

    public IndexModel(IEnumerable<ISomething> someThings,
        IEnumerable<Lazy<ISomething>> someLazyThings)
    {
        _someThings = someThings;
        _someLazyThings = someLazyThings;
    }
    public void OnGet()
    {
        List<string> names = new List<string>();
        var countSomeThings = _someThings.Count();  // 2 as expected
        var countSomeLazyThings = _someLazyThings.Count(); // 1. huh?
        foreach (var lazyObject in _someLazyThings)
        {
            names.Add(lazyObject.Value.Name);
        }
    }
}

我还没有深入挖掘资料来找出我为什么不能获得2

 IEnumerable<Lazy<ISomething>>

//services.AddLazier();//REMOVED
services.AddTransient<ISomething, SomeThing1>();
services.AddTransient<ISomething, SomeThing2>();
services.AddLazyTransient<ISomething, SomeThing1>();
services.AddLazyTransient<ISomething, SomeThing2>();

结果(按我的意思工作)..

public class IndexModel : PageModel
{
    private IEnumerable<ISomething> _someThings;
    private IEnumerable<Lazy<ISomething>> _someLazyThings;

    public IndexModel(IEnumerable<ISomething> someThings,
        IEnumerable<Lazy<ISomething>> someLazyThings)
    {
        _someThings = someThings;
        _someLazyThings = someLazyThings;
    }
    public void OnGet()
    {
        List<string> names = new List<string>();
        var countSomeThings = _someThings.Count();  // 2 as expected
        var countSomeLazyThings = _someLazyThings.Count(); // 2 as expected
        foreach (var someLazyThing in _someLazyThings)
        {
            names.Add(someLazyThing.Value.Name);
        }
    }
}

下面的IServiceCollection扩展显示了我如何注册服务。

foreach (var exchange in exchanges)
{
    services.AddTransient<Lazy<ITokenExchangeHandler>>(serviceProvider =>
    {
        return new Lazy<ITokenExchangeHandler>(() =>
        {
            var tokenExchangeHandler = serviceProvider.GetRequiredService<PipelineTokenExchangeHandler>();
            tokenExchangeHandler.Configure(exchange);
            return tokenExchangeHandler;
        });
    }); 
}

public static class AspNetCoreServiceCollectionExtensions
{

    public static IServiceCollection AddLazyTransient<TService, TImplementation>(this IServiceCollection services)
        where TService : class
        where TImplementation : class, TService
    {
        services.AddTransient<TImplementation>();
        services.AddTransient<Lazy<TService>>(serviceProvider =>
        {

            return new Lazy<TService>(() =>
            {
                var impl = serviceProvider.GetRequiredService<TImplementation>();
                return impl;
            });
        });
        return services;
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.