1、前言

面向对象设计(OOD)里有一个重要的思想就是依赖倒置原则(DIP),并由该原则牵引出依赖注入(DI)、控制反转(IOC)及其容器等概念。在学习Core依赖注入、服务生命周期之前,下面让我们先了解下依赖倒置原则(DIP)、依赖注入(DI)、控制反转(IOC)等概念,然后再深入学习Core依赖注入服务。

2、依赖倒置原则(Dependency Inversion  Principle, DIP

抽象不应该依赖于细节,细节应当依赖于抽象,高层模块不依赖于低层模块的实现,而低层模块依赖于高层模块定义的接口。一般来讲,就是高层模块定义接口,低层模块负责具体的实现。针对接口编程而不是针对细节编程

3、什么是依赖注入(Denpendency Injection)

3.1、依赖

人与人之间都有依赖(尤其我,就是离不开女人哈哈)何况软件呢?所谓依赖就是:当一个类需要另一个类协作来完成工作的时候就产生了依赖。比如用户登录,我们在控制器中UserController要完成用户登录、注册、修改密码等等事情、其中操作到数据库的(登录)我们用EF来完成,这里我们封装了一个EFLogin,这里的UserController就有一个ILogin的依赖。需要知道的是这里依赖于一个抽象为不是具体的某一个实现,所以给EFLogin定义了一个接口ILogin抽象了EFLogin的行为

3.2、注入

注入体现的是一个IOC(控制反转的的思想)。

 public interface IUser
{
string BB();
}
public class User : IUser
{
public string BB()
{
return "LP整天只会BB";
}
}
public class ShowInfo
{
IUser user = new User();
public void UserBB()
{
user.BB();
}
}

当我们调用ShowInfo的时候,是通过IUser接口实例化一个User类去实现其方法的这叫控制正传, 但是大湿兄说,我们不应该创建User类,而是让调用者给你传递,于是你通过构造函数让外界把这两个依赖给你。把依赖的创建丢给其它人。自己只负责使用,其它人丢给你依赖的这个过程理解为注入其它人丢给你依赖的这个过程理解为注入。也叫控制反转(IOC)

public interface IUser
{
string BB();
}
public class User : IUser
{
public string BB()
{
return "LP整天只会BB";
}
} public class ShowInfo2
{
private readonly IUser _user;
public ShowInfo2 (IUser user)
{
_user = user;
}
public void UserBB()
{
_user.BB();
}
}

3.3、为什么要使用依赖注入?

使用依赖注入我们可以很好的管理类跟类之间的依赖,在我们设计应用程序的时候遵循这几原则,确保代码的可维护性和扩展性;另外在Core的架构中依赖注入提供了对象创建和生命周期管理的核心能力,各个组件之间的相互协作也是由依赖注入框架来实现的

4、服务生命周期

在ConfigureServices方法中的容器注册每个应用程序的服务,Asp.Core都可以为每个应用程序提供三种服务生命周期:
Transient(暂时):每次请求都会创建一个新的实例。这种生命周期最适合轻量级,无状态服务。
Scoped(作用域):在同一个作用域内只初始化一个实例 ,可以理解为每一个请求只创建一个实例,同一个请求会在一个作用域内。在Scooped的生存周期内,如果容器释放 它也就被释放了
Singleton(单例):整个应用程序生命周期以内只创建一个实例,后续每个请求都使用相同的实例。如果应用程序需要单例行为,建议让服务容器管理服务的生命周期,而不是在自己的类中实现单例模式。

为了演示生命周期和注册选项之间的差异,请考虑以下代码:

IGuid接口返回一个Guid

public interface IGuid
{
Guid GetGuid { get; }
}

接口IScopedService、ISingletonService、ITransientService、都继承接口IGuid

 public interface IScopedService:IGuid
{ }
public interface ISingletonService: IGuid
{ }
public interface ITransientService: IGuid
{ }
 GuidShow类继承接口IScopedService、ISingletonService、ITransientService
public class GuidShow : IScopedService, ISingletonService, ITransientService
{ public GuidShow() : this(Guid.NewGuid())
{
}
public GuidShow(Guid id)
{
GetGuid = id;
}
public Guid GetGuid { get; private set; } }

在Starup里面注册

public void ConfigureServices(IServiceCollection services)
{
#region//注册不同生命周期的服务
services.AddSingleton<ISingletonService, SingletonService>();
services.AddTransient<ITransientService, TransientService>();
services.AddScoped<IScopedService, ScopedService>();
#endregion
services.AddControllers();
}

在WeatherForecastController Api里写一个Api

FromServices就是从容器里面获取我们的对象 每个对象都获取两边来来对比每个生命周期是怎么样的
 [ApiController]
[Route("[controller]/[action]")]
//路由
//API
[HttpGet]
public string GetService(
[FromServices] IScopedService scoped1, [FromServices] IScopedService scoped2,
[FromServices] ITransientService transient1, [FromServices] ITransientService transient2,
[FromServices] ISingletonService singleton, [FromServices] ISingletonService singleton2)
{
Console.WriteLine();
Console.WriteLine(); Console.WriteLine($"作用域1-->{scoped1.GetGuid}");
Console.WriteLine($"作用域2-->{scoped2.GetGuid}"); Console.WriteLine();
Console.WriteLine();
Console.WriteLine($"瞬时1-->{transient1.GetGuid}");
Console.WriteLine($"瞬时2-->{transient2.GetGuid}"); Console.WriteLine();
Console.WriteLine();
Console.WriteLine($"单例1-->{singleton.GetGuid}");
Console.WriteLine($"单例2-->{singleton2.GetGuid}"); Console.WriteLine("===========分割线=====================");
Console.WriteLine();
Console.WriteLine(); return "成功";
}

修改应用程序启动

启动应用程序

可以看出来单例跟作用域的都是一样的Guid 只有瞬时的不一样  再次刷新浏览器

单例的没有改变所以

Transient(暂时):每次调用服务的时候都会创建一个新的实例

 Scoped(作用域):一次请求(Action)内对象实例是相同的,但每次请求会产生一个新实例。

Singleton(单例):首次请求初始化同一个实例,后续每次请求都使用同一个实例。相当于在整个应用Application中只实例化一次实例,常见的单例模式。

下面是其他的注册

  #region//工程模式注册 单例作用域、瞬时 都可以用
services.AddSingleton<ISingletonService>(s=> {
return new SingletonService();
});
   #region//尝试注册
//注册过了就不在注册了
//using Microsoft.Extensions.DependencyInjection.Extensions;
services.TryAddScoped<IScopedService, ScopedService>();
#endregion
#region//移除注册 移除所有IScopedService的注册 不同实现的
 services.RemoveAll<IScopedService>(); #endregion

注册泛型 先写一个泛型类

 public interface ITypeT<T>
{
}
public class TypeT<T> : ITypeT<T>
{
public T GetT { get; }
public TypeT(T getT)
{
this.GetT = getT;
}
}

创建一个api Test

[Route("api/[controller]/[action]")]
[ApiController]
public class TestController : ControllerBase
{
public ITypeT<IScopedService> _typeT;
public TestController(ITypeT<IScopedService> typeT)
{
_typeT = typeT;
} [HttpGet]
public string TestGet()
{
return _typeT.GetHashCode().ToString();
}
}

注册一下 里面具体的参数不用谢 实现的时候只要带入某个具体的类就可以了,第一个参数服务的额类型,第二个参数服务的实现类型

     services.AddScoped(typeof(ITypeT<>),typeof(TypeT<>));

地址栏输入https://localhost:5001/api/test/testGet

看断点

GetT他得到的是ScopedService

5、依赖注入的方式

5.1、构造函数注入

我们可以在定义的Controller中以构造函数注入的方式注入所需的服务。他的服务是大部分接口都需要的话就用它

public ITypeT<IScopedService> _typeT;
public TestController(ITypeT<IScopedService> typeT)
{
_typeT = typeT;
}

5.2、FromServices

上面的GetService就是这种方式注入的,这个服务只是在某一个接口下用FromServices

当然还有其他的注入方式就不在研究了。

原文链接:https://www.cnblogs.com/w5942066/p/12808405.html

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)的更多相关文章

  1. ASP.NET Core中如影随形的”依赖注入”[下]: 历数依赖注入的N种玩法

    在对ASP.NET Core管道中关于依赖注入的两个核心对象(ServiceCollection和ServiceProvider)有了足够的认识之后,我们将关注的目光转移到编程层面.在ASP.NET ...

  2. ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起

    我们一致在说 ASP.NET Core广泛地使用到了依赖注入,通过前面两个系列的介绍,相信读者朋友已经体会到了这一点.由于前面两章已经涵盖了依赖注入在管道构建过程中以及管道在处理请求过程的应用,但是内 ...

  3. [ASP.NET Core 3框架揭秘] 依赖注入:控制反转

    ASP.NET Core框架建立在一些核心的基础框架之上,这些基础框架包括依赖注入.文件系统.配置选项和诊断日志等.这些框架不仅仅是支撑ASP.NET Core框架的基础,我们在进行应用开发的时候同样 ...

  4. [ASP.NET Core 3框架揭秘] 依赖注入[5]: 利用容器提供服务

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

  5. [ASP.NET Core 3框架揭秘] 依赖注入[8]:服务实例的生命周期

    生命周期决定了IServiceProvider对象采用怎样的方式提供和释放服务实例.虽然不同版本的依赖注入框架针对服务实例的生命周期管理采用了不同的实现,但总的来说原理还是类似的.在我们提供的依赖注入 ...

  6. [ASP.NET Core 3框架揭秘] 依赖注入[10]:与第三方依赖注入框架的适配

    .NET Core具有一个承载(Hosting)系统,承载需要在后台长时间运行的服务,一个ASP.NET Core应用仅仅是该系统承载的一种服务而已.承载系统总是采用依赖注入的方式来消费它在服务承载过 ...

  7. [ASP.NET Core 3框架揭秘] 依赖注入[9]:实现概述

    <服务注册>.<服务消费>和<生命周期>主要从实现原理的角度对.NET Core的依赖注入框架进行了介绍,接下来更进一步,看看该框架的总体设计和实现.在过去的多个版 ...

  8. [ASP.NET Core 3框架揭秘] 依赖注入[7]:服务消费

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

  9. [ASP.NET Core 3框架揭秘] 依赖注入[6]:服务注册

    通过<利用容器提供服务>我们知道作为依赖注入容器的IServiceProvider对象是通过调用IServiceCollection接口的扩展方法BuildServiceProvider创 ...

随机推荐

  1. Hadoop入门之hdfs

        大数据技术开篇之Hadoop入门[hdfs] 学习都是从了解到熟悉的过程,而学习一项新的技术的时候都是从这个技术是什么?可以干什么?怎么用?如何优化?这几点开始.今天这篇文章分为两个部分.一. ...

  2. RabbitMQ集群架构(HA)并结合.NET Core实操

    一.前言 已经一年没有更新博客了,由于公司事务比较多,并且楼主我也积极在公司项目中不断实践.net core.DDD以及Abp vnext,也积累了一些吐血经验,目前我在做一家在线教育公司负责智慧校园 ...

  3. 1098 Insertion or Heap Sort (25分)

    According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, and gr ...

  4. 微信小程序placeholder设置自定义颜色

    原地址链接:https://blog.csdn.net/august_leo/article/details/80877382 这是微信小程序input组件的官方文档描述,下图红框里的placehol ...

  5. js定义类的方法

    ECMAScript6已经支持了class,但之前版本都不支持类,但是可以通过一些方法来模拟类. js中的类,既是重点,也是难点,很多时候都感觉模棱两可. 首先强调一下js中很重要的3个知识点:thi ...

  6. Jquery的$.get(),$.post(),$.ajax(),$.getJSON()用法详细解读

    1.$.get $.get()方法使用GET方式来进行异步请求,它的语法结构为: $.get( url [, data] [, callback] ) 解释一下这个函数的各个参数: url:strin ...

  7. Powershell基础---帮助系统

    帮助系统能带给我们什么? 1.快速找到命令,无需使用Bing或者Google 2.运行命令时候返回了错误信息,帮助系统可以告诉我们如何正确使用该命令 3.多个命令组合执行完成复杂的工作,帮助系统告诉我 ...

  8. loadrunner post请求

    注意:loadrunner参数中的引号,需要自己加"\" post 请求,分为header 和body两个部分处理 header部分比较容易处理,使用函数实现,如web_add_h ...

  9. ClassLoader类加载器浅见

    类加载器 类加载器,它拿到.class文件,它会把他拆成两部分,将static数据转换成方法区的数据结构,然后把他放在了方法区之中. 然后在堆里面建一个类对象(Class,它可以用来实例化对象),然后 ...

  10. AJ学IOS(54)多线程网络之NSOperation重要知识

    AJ分享,必须精品 一:队列的类型与队列添加任务 1: 主队列 [NSOperationQueue mainQueue] 添加到”主队列”中的操作,都会放到主线程中执行. 2:非主队列 [[NSOpe ...