有些對象咱們並不想一開始就實例化,因爲性能或者功能的考慮,但願等到使用的時候再實例化。
考慮存在一個類 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