最新在朋友那里看到有问这个Lazy是干什么用的,深思熟虑以后决定写一篇记录博客,记录以往的学习成果-
概念:延时加载(延时实例化或延时初始化)重点是延时,用时加载。意思是对象在使用的时候创建而不是在实例化的的时候才创建。
延时加载主要应用的场景:
1:数据层(ADO.NET或Entity Framework等ORM,Java里面的Hibernate也用到了这种技术)
2:反射(加载Assemblier,Type,MEF)
3:缓存对象,领域实体
4:解决.Net依赖注入或者Core依赖注入的循环依赖注入导致的异常问题
当然,我们目前用到延时最多的场景想必就是EF或者EF Core,我们在使用的时候声明上下文,通过委托表达式来筛选条件,在最后的时候我们会用上一个Tolist();调试过得人应该都知道,只有在ToList()的时候数据才会真正的从数据库查询出来,在此之前一切都是铺垫。
如下:
DbContext db=new DbContext (); var Data=db.表明(实体).条件.ToList();
同理:Lazy也如此去理解,但是使用范围相当广泛,在此就列举基本的使用方法和封装方法,如下:
首先我们来测试Lazy的周期是否符合我们的理论观点:
Test类中CWTest是测试方法,本文所有Test均是如下图意思
官方提供的方法重载如下:
有很多重载:
1:委托创建对象
2:判断是否线程安全:
3:获取目前存在的县城信息:
4:以及针对某个委托的创建的实例是否线程安全
5:某委托创建的线程模型信息
其他扩展:
1:判断是否创建成功:
2:创建的实例返回
使用方法1:
运行后:
我们看到在Lazy声明时,我们的实例在内存中是不存在的,
在Way1.Value.CWTest();调用后,我们才检索到我们的实例
使用方法2:
运行后:
与第一种区别不大,周期依然符合理论
使用方法3:
运行后:
我们通过拉姆达表达式去New一个实例并返回给Lazy的泛型重载,
周期依然符合理论
使用方法4:
通过工厂,在工厂内部动态的调用待创建的实例并进行Build返回给业务层。
////// 自定义封装懒加载 /// ///public class MyLazy { private volatile object boxed; //volatile说明在多线程状况下,也可以修改该字段 private Func valueFactory; //委托,用来生产T对象实例 static MyLazy() { } public MyLazy() { } public MyLazy(Func valueFactory) { this.valueFactory = valueFactory; } public T Value { get { Boxed boxed = null; if (this.boxed != null) { boxed = this.boxed as Boxed; if (boxed != null) { return boxed.value; } } return this.Init(); } } //初始化对象实例 private T Init() { Boxed boxed = null; if (this.boxed == null) { boxed = this.CreateValue(); this.boxed = boxed; } return boxed.value; } //创建内部类实例 private Boxed CreateValue() { //如果创建对象实例的委托valueFactory存在 if (this.valueFactory != null) { //就通过委托生成对象实例 return new Boxed(this.valueFactory()); } else { //否则,通过反射生成对象实例 return new Boxed((T)Activator.CreateInstance(typeof(T))); } } //内部嵌套类,通过构造函数对其字段赋值 private class Boxed { internal T value; internal Boxed(T value) { this.value = value; } } }
运行后:
结果依然符合我们的理论逻辑,以上就是Lazy懒加载(实例延时声明的基本使用扩展)
文章内容有待大神进行指点,虚心请教!



