Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

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的行为

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

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(单例):整个应用程序生命周期以内只建立一个实例,后续每个请求都使用相同的实例。若是应用程序需要单例行为,建议让服务容器治理服务的生命周期,而不是在自己的类中实现单例模式。

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

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

 

 

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 "乐成";
        }

 

修改应用程序启动

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

 

启动应用程序

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

 

 

备忘录模式 (c++实现)

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

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

 

 

 单例的没有改变以是

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

看断点

Asp.Net Core 3.1学习-依赖注入、服务生命周期(6)

 

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

 

原创文章,作者:28x29新闻网,如若转载,请注明出处:https://www.28x29.com/archives/6860.html