有些对象我们并不想一开始就实例化,由于性能或者功能的考虑,希望等到使用的时候再实例化。
考虑存在一个类 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 的实例,它才会实例化。

依赖注入在 dotnet core 中实现与使用:3 使用 Lazy<T> 延迟实例化的更多相关文章

  1. 依赖注入在 dotnet core 中实现与使用:1 基本概念

    关于 Microsoft Extension: DependencyInjection 的介绍已经很多,但是多数偏重于实现原理和一些特定的实现场景.作为 dotnet core 的核心基石,这里准备全 ...

  2. 依赖注入在 dotnet core 中实现与使用:2 使用 Extensions DependencyInjection

    既然是依赖注入容器,必然会涉及到服务的注册,获取服务实例,管理作用域,服务注入这四个方面. 服务注册涉及如何将我们的定义的服务注册到容器中.这通常是实际开发中使用容器的第一步,而容器本身通常是由框架来 ...

  3. 依赖注入在 dotnet core 中实现与使用:4. 集成 Autofac

    本示例使用 .net core 5 rc-1 实现. 1. 添加 Nuget 包引用 使用 Autofac 当然要添加 Autofac 的 Nuget 包,主要涉及到两个: Autofac.Exten ...

  4. Dotnet Core中使用AutoMapper

    官网:http://automapper.org/ 文档:https://automapper.readthedocs.io/en/latest/index.html GitHub:https://g ...

  5. 依赖注入[8]: .NET Core DI框架[服务消费]

    包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IServiceProvider对象.当需要消费某个服务实例的时候,我们只需要指定服务类型调用IServicePr ...

  6. 依赖注入[7]: .NET Core DI框架[服务注册]

    包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IServiceProvider对象.服务注册就是创建出现相应的ServiceDescriptor对象并将其添加到 ...

  7. 依赖注入[6]: .NET Core DI框架[编程体验]

    毫不夸张地说,整个ASP.NET Core框架是建立在一个依赖注入框架之上的,它在应用启动时构建请求处理管道过程中,以及利用该管道处理每个请求过程中使用到的服务对象均来源于DI容器.该DI容器不仅为A ...

  8. .NET CORE学习笔记系列(2)——依赖注入[7]: .NET Core DI框架[服务注册]

    原文https://www.cnblogs.com/artech/p/net-core-di-07.html 包含服务注册信息的IServiceCollection对象最终被用来创建作为DI容器的IS ...

  9. .NET CORE学习笔记系列(2)——依赖注入[6]: .NET Core DI框架[编程体验]

    原文https://www.cnblogs.com/artech/p/net-core-di-06.html 毫不夸张地说,整个ASP.NET Core框架是建立在一个依赖注入框架之上的,它在应用启动 ...

随机推荐

  1. C语言程序设计100例之(15):除法算式

    例15   除法算式 问题描述 输入正整数n(2≤n≤68),按从小到大输出所有形如abcde/fghi=n的表达式.其中a~i为1~9的一个排列. 输入格式 每行为一个正整数n (n <= 1 ...

  2. 单个div元素实现双边框

    昨天被问到一个很有意思的问题,单个div元素怎么实现双边框,当时脑子懵了一下,然后就回答出来用伪元素,别的实在是想不起来了,所以在此总结一下子防止以后再被问到 总结了一下大约有以下几种方案: 伪元素实 ...

  3. 清新三角格子风工作报告季度总结年终汇报通用PPT模板

    选好合适的PPT模板,确定好主题,一个漂亮的PPT首先要简洁,其次文字不要太多,能用图片或视频讲解的最好用图片或视频.做好ppt后,对于讲解演示,也要提前做好练习准备. 模版来源:http://ppt ...

  4. 【JS基础语法】---学习roadmap---6 parts

    JS基础语法---roadmap Part 1 - 2: Part 3 - 4:   Part 5 - 6

  5. 【转】Kotlin的inline内联函数

    原文链接:https://blog.csdn.net/Jaden_hool/article/details/78437947 方法调用流程 调用一个方法是一个压栈和出栈的过程,调用方法时将栈针压入方法 ...

  6. iOS 为何使用runtime方法交换多次后却能按照交换顺序依次执行代码逻辑?

    题目: 假设我们有一个ViewController, Category A(ViewController), Category B(ViewController), Category C(ViewCo ...

  7. eclipse git 主干代码合并到分支

    https://blog.csdn.net/wwd0501/article/details/80676807 eclipse git 主干代码合并到分支: 1.项目切换至分支: 2.选中项目右键--& ...

  8. 一文解读HTTP2 (转)

    作为一个经常和web打交道的程序员,了解这些协议是必须的,本文就向大家介绍一下这些协议的区别和基本概念,文中可能不局限于前端知识,还包括一些运维,协议方面的知识,希望能给读者带来一些收获,如有不对之处 ...

  9. [20191031]完善vim的bccalc插件7.txt

    [20191031]完善vim的bccalc插件7.txt --//增加/ 2^16 %2^16功能,输入\tx,例子:1398145029 = /2^16  %2^16 (type and mode ...

  10. java8-04-初识函数式接口

    为什么用函数式接口                                   在函数式编程思想下,允许函数本身作为参数传入另一个函数.使用函数式接口实现"传递行为"的思想 ...