使用.net core 內建DI架構實現 消極式載入

來源:互聯網
上載者:User

標籤:type   ram   extension   amp   sts   microsoft   etc   區別   ack   

在某些情況,我們希望能延遲一個依賴的初始化。如果使用的是autofac,我們可以通過注入Lazy

我們對 autofac GitHub上提供的一個例子進行進行簡單改造,跑起來看看。
原Example的連結https://github.com/autofac/Examples/tree/master/src/AspNetCoreExample

微改後的代碼

[Route("api/[controller]")]public class ValuesController : Controller{    private readonly Lazy<IValuesService> _valuesService;    public ValuesController(Lazy<IValuesService> valuesService)    {        _valuesService = valuesService;    }    // GET api/values    [HttpGet]    public IEnumerable<string> Get()    {        // Kestrel模式下這裡會輸出false,執行個體尚未建立        Console.WriteLine(_valuesService.IsValueCreated);         // 調用Lazy<T>的Value屬性才真正建立執行個體        return this._valuesService.Value.FindAll();    }}

直到目前core2.1版本,內建的DI依舊未支援消極式載入,如果我們嘗試在使用內建DI的情況下套用上述代碼,會得到一個異常,例如:

An unhandled exception occurred while processing the request.

InvalidOperationException: Unable to resolve service for type ‘System.Lazy`1[WebApplication9.Services.IValuesService]‘ while attempting to activate ‘WebApplication9.Controllers.ValuesController‘.

Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)

如何利用core內建的DI實現呢?如果我們嘗試百度,可能會搜到類似下面的答案。

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

那麼這樣的做法是否能解決我們的問題呢,為了簡化示範代碼。我們建立一個控制台程式並引用Microsoft.Extensions.DependencyInjection。

class Program{    static void Main(string[] args)    {        var services = new ServiceCollection();        services.AddScoped<ITestService, TestService>();        services.AddTransient(typeof(Lazy<>));        var serviceProvider = services.BuildServiceProvider();        using (var scope = serviceProvider.CreateScope() )        {            var service = scope.ServiceProvider.GetService<Lazy<ITestService>>();            // 這邊令人遺憾地輸出了true,也就是說,這種方式的延遲注入是失敗的            Console.WriteLine(service.IsValueCreated);        }    }}

在查閱Stack Overflow的時候,我看到了這樣的解決方案,感覺還是挺簡單實用的,分享給大家。

原貼地址:https://stackoverflow.com/questions/44934511/does-net-core-dependency-injection-support-lazyt

public class LazyLoader<T> : Lazy<T>{    public LazyLoader(IServiceProvider sp) : base(sp.GetRequiredService<T>)    {    }}class Program{    static void Main(string[] args)    {        var services = new ServiceCollection();        services.AddScoped<ITestService, TestService>();        // services.AddScoped(typeof(Lazy<>), typeof(LazyLoader<>)); 也可以,區別不大        services.AddTransient(typeof(Lazy<>), typeof(LazyLoader<>));        var serviceProvider = services.BuildServiceProvider();        using (var scope = serviceProvider.CreateScope())        {            var service = scope.ServiceProvider.GetService<Lazy<ITestService>>();            Console.WriteLine(service.IsValueCreated); // 輸出false            // 下面輸出true,延遲注入的對象和正常注入的對象,本質上不會有差別            Console.WriteLine(service.Value == scope.ServiceProvider.GetService<ITestService>());        }    }}

實現原理比較簡單,在LazyLoader中注入ServiceProvider,調用父類的Value屬性時會執行委託,從ServiceProvider中擷取到對應得依賴執行個體。

使用.net core 內建DI架構實現 消極式載入

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.