依賴注入在 dotnet core 中實現與使用:3 使用 Lazy 延遲實例化


 

有些對象我們並不想一開始就實例化,由於性能或者功能的考慮,希望等到使用的時候再實例化。
考慮存在一個類 A, 它使用了依賴的類 B,在 A 中,只有某些不常用到的方法會涉及調用 B 中的方法,多數情況下,並不使用這個 B 的實例。

using System;

public class A {
    private B _b;
    public A (B b) {
        _b = b;
        Console.WriteLine("construct class A...");
    }

    public void MethodOne () {
        _b.ClassBMethod ();
    }

    public void MethodTwo () {
        // does not use _b 
    }

    public void MethodThree () {
        // does not use _b 
    }
}

public class B {

    public B (){
        Console.WriteLine("construct class b......");
    }
    public void ClassBMethod () { //do something } 
    }
}

 

把它們注冊到容器中,然后使用一下。

using System;
using Microsoft.Extensions.DependencyInjection;

class Program {
    static void Main (string[] args) {
        IServiceCollection services = new ServiceCollection ();

        services.AddSingleton<B>();
        services.AddSingleton<A>();

        var provider = services.BuildServiceProvider();
        var a = provider.GetService<A>();
        a.MethodTwo();
        a.MethodThree();
    }
}

這里僅僅調用了類 A 的 MethodTwo() 和 MethodThree() 這兩個方法,那么,對於類 B 的實例化就是沒有必要的。但是,從輸出中可以看到,由於類 A 依賴了類 B,所以,B 被提前實例化了。

construct class b......
construct class A...

 

在這種情況下,如何可以避免對類 B 的實例化呢?考慮使用 Lazy<T> 。

當通過 Lazy<T> 的方式注入依賴的類型的時候,我們將延遲了對所依賴對象的構造,而且,Lazy<T> 會被自動注入,與使用注冊在容器中的 T 一樣。

Layz<T> 表示在第一次訪問的時候才會初始化的值。上面的代碼可以修改為如下形式:

using System;

public class A {
    private Lazy<B> _b;
    public A (Lazy<B> b) {
        _b = b;
        Console.WriteLine("construct class A...");
    }

    public void MethodOne () {
        _b.Value.ClassBMethod ();
    }

    public void MethodTwo () {
        // does not use _b 
    }

    public void MethodThree () {
        // does not use _b 
    }
}

public class B {

    public B (){
        Console.WriteLine("construct class b......");
    }
    public void ClassBMethod () { //do something } 
    }
}

 

注冊的形式也需要調整一下。

static void Main (string[] args) {
    IServiceCollection services = new ServiceCollection ();
    
    services.AddSingleton<Lazy<B>>();  
    services.AddSingleton<A>();

    var provider = services.BuildServiceProvider();
    var a = provider.GetService<A>();
    a.MethodTwo();
    a.MethodThree();
    Console.WriteLine("prepare call MethodOne...");
    a.MethodOne();
}

 

對類型 B 的注冊,變成了注冊 Lazy<B>。它是 B 的一個封裝。

現在重新運行程序,可以看到如下的結果。

construct class A...
prepare call MethodOne...
construct class b......

 

在調用 MethodTwo() 和 MethodThree() 的時候,類型 B 並沒有實例化,直到實際調用 MethodOne() 的時候,實際訪問了類型 B 的實例,它才會實例化。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM