zoukankan      html  css  js  c++  java
  • 依赖注入在 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 的实例,它才会实例化。

  • 相关阅读:
    websocket 学习笔记
    oxy 学习笔记
    postcss
    一致性hash和chord
    leveldb 学习笔记
    logrus 学习笔记
    viper 学习笔记
    redigo 学习笔记
    gin 学习笔记
    修改TOMCAT的JVM虚拟机内存大小几种方式
  • 原文地址:https://www.cnblogs.com/haogj/p/11450422.html
Copyright © 2011-2022 走看看