ASP.NET泛型四之使用Lazy<T>实现延迟加载

 更新时间:2022年08月13日 11:30:56   作者:Darren Ji  
这篇文章介绍了ASP.NET泛型使用Lazy<T>实现延迟加载的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

".NET泛型"系列:

ASP.NET泛型一之泛型简介与基本语法

ASP.NET泛型二之泛型的使用方法

ASP.NET泛型三之使用协变和逆变实现类型转换

ASP.NET泛型四之使用Lazy<T>实现延迟加载

对于一些"大对象"的创建,我们常常希望延迟加载,即在需要的时候再创建对象实例。现在Lazy<T>很好地支持了这一特点。主要包括:

没有Lazy<T>之前

在没有Lazy<T>之前,我们通过如下方式实现延迟加载。

public class LazySinleton
{
    private LazySingleton()
    {}
 
    public static LazySingleton Instance
    {
        get
        {
            return Lazy.data;
        }
    }
 
    private class Lazy
    {
        static Lazy()
        {}
 
        internal static readonly LazySingleton data = new LazySingleton();
    }
}

以上

  • 通过私有构造函数屏蔽了LazySingleton类通过构造函数创建的方式
  • 私有嵌套类Lazy的data字段负责提供一个LazySingleton的实例
  • 只能通过LazySingleton的属性Instance,才能拿到内部类Lazy.data所代表的实例

Lazy<T>实例

先看Lazy<T>的定义:

public class Lazy<T>
{
    public Lazy();
    public Lazy(bool isThreadSafe);
    public Lazy(Func<T> valueFactory);
    public Lazy(LazyThreadSafeMode mode);
    public Lazy(Func<T> valueFactory, bool isThreadSafe);
    public Lazy(Funct<T> valueFactory, LazyThreadSafetyMode mode);

    public bool IsValueCreated{get;}
    public T Value {get;}
    public override string ToStirng();
}

通过Lazy<T>的构造函数重载创建对象,再通过体现延迟加载的Value属性来实现对象的创建,并获取对象实例。

public class SomeClass
{
    public int ID{get;set;}
}

Lazy<SomeClass> temp = new Lazy<SomeClass>();
Console.WriteLine(temp.Value.ID);

以上,只适用于没有构造函数的情况,如果有构造函数如何处理呢?
--使用public Lazy(Func<T> valueFactory),通过委托创建对象

pubic class SomeClass
{
    public int ID{get;set;}
    public SomeClass(int id)
    {
        this.ID = id;
    }
}

Lazy<SomeClass> temp = new Lazy<SomeClass>(() => new Big(100));
Console.WriteLine(temp.Value.ID);

延迟加载的本质

创建自定义延迟加载类。

    public class MyLazy<T>
    {
        private volatile object boxed; //volatile说明在多线程状况下,也可以修改该字段
        private Func<T> valueFactory; //委托,用来生产T对象实例

        static MyLazy(){}
        public MyLazy(){}

        public MyLazy(Func<T> 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;
            }
        }
    }

自定义带构造函数的类。

    public class Big
    {
        public int ID { get; set; }
        public Big(int id)
        {
            this.ID = id;
        }
    }

自定义创建对象实例的工厂类。

    public class BigFactory
    {
        public static Big Build()
        {
            return new Big(10);
        }
    }

客户端调用。

    class Program
    {
        static void Main(string[] args)
        {
            MyLazy<Big> temp = new MyLazy<Big>(() => BigFactory.Build());
            Console.WriteLine(temp.Value.ID);
            Console.ReadKey();
        }
    }

延迟加载的本质大致是:

  • 由延迟加载类的内部嵌套类产生对象实例
  • 再通过延迟加载类的某个属性来延迟获取对象实例,而对象实例是通过委托等方式创建的

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。如果你想了解更多相关内容请查看下面相关链接

相关文章

  • MVC+EasyUI+三层新闻网站建立 详情页面制作方法(八)

    MVC+EasyUI+三层新闻网站建立 详情页面制作方法(八)

    这篇文章主要为大家详细介绍了MVC+EasyUI+三层新闻网站建立的第八篇,教大家如何制作详情页面,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07
  • .NET ORM框架SqlSugar实现导航查询功能

    .NET ORM框架SqlSugar实现导航查询功能

    今天这篇文章分享一款好用简单的ORM框架 SqlSugar,相比 EF Core的导航查询更加简单,配置更加容易,几分钟就能上手,对.NET ORM框架SqlSugar实现导航查询功能感兴趣的朋友一起看看吧
    2022-04-04
  • .NetCore之接口缓存的实现示例

    .NetCore之接口缓存的实现示例

    这篇文章主要介绍了.NetCore之接口缓存的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • c# indexof 用法深入理解

    c# indexof 用法深入理解

    在开发过程中经常会使用到c# indexof 查找字串中指定字符或字串首次出现的位置,返首索引值,本文将详细介绍,需要的朋友可以参考下
    2012-11-11
  • 推荐8项提高 ASP.NET Web API 性能的技术

    推荐8项提高 ASP.NET Web API 性能的技术

    ASP.NET Web API 是非常棒的技术。编写 Web API 十分容易,以致于很多开发者没有在应用程序结构设计上花时间来获得很好的执行性能。
    2014-08-08
  • 基于asp.net实现图片在线上传并在线裁剪功能

    基于asp.net实现图片在线上传并在线裁剪功能

    本文主要介绍了基于asp.net实现图片在线上传并在线裁剪功能的具体事例代码,具有一定的参考价值。需要的朋友可以参考下
    2016-12-12
  • asp.net 需要登陆的网站上下载网页源代码和文件

    asp.net 需要登陆的网站上下载网页源代码和文件

    最近有个项目需要从网络上下载网页信息和文件,并且需要登录后才能下载,所以做了个下载的通用类,供大家参考。
    2009-05-05
  • 全面剖析.Net环境下的缓存技术

    全面剖析.Net环境下的缓存技术

    这篇文章主要全面剖析.Net环境下的缓存技术,介绍缓存的基本概念和常用的缓存技术,给出了各种技术的实现机制的简单介绍和适用范围说明,以及设计缓存方案应该考虑的问题,感兴趣的小伙伴们可以参考一下
    2016-03-03
  • moq 的常用使用方法(推荐)

    moq 的常用使用方法(推荐)

    这篇文章主要介绍了moq 的常用使用方法的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-11-11
  • MVC+EasyUI+三层新闻网站建立 建站准备工作(一)

    MVC+EasyUI+三层新闻网站建立 建站准备工作(一)

    这篇文章主要为大家详细介绍了MVC+EasyUI+三层新闻网站建立的第一篇,建站的准备工作,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-07-07

最新评论