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

 

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

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 被提早實例化了。ui

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

 

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

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

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 } 
    }
}

 

註冊的形式也須要調整一下。blog

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 的一個封裝。string

如今從新運行程序,能夠看到以下的結果。it

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

 

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

相關文章
相關標籤/搜索