依赖注入在 dotnet core 中实现与使用:3 使用 Lazy<T> 延迟实例化
有些对象我们并不想一开始就实例化,由于性能或者功能的考虑,希望等到使用的时候再实例化。
考虑存在一个类 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 的实例,它才会实例化。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
2015-09-02 使用 Jasmine 进行测试驱动的 JavaScript 开发
2013-09-02 Bootstrap 3 How-To #2 标题,链接与按钮