NETCORE - 依赖注入

NETCORE - 依赖注入

 

依赖:当一个类需要另一个类协作来完成工作的时候就产生了依

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

在反转之前 ,我们先看看正转。 AccountController自己来实例化需要的依 
private ILoginService<ApplicationUser> _loginService;
public AccountController()
{
  _loginService = new EFLoginService()
}

 

 大师说,这样不好。你不应该自己创建它,而是应该由你的调用者给你。于是你通过构造函数让外界把这两个依传给你。

public AccountController(ILoginService<ApplicationUser> loginService)
{
  _loginService = loginService;
}

 

 把依赖的创建丢给其它人,自己只负责使用,其它人丢给你依赖的这个过程理解为注入。

 

 

反转?

为了在业务变化的时候尽少改动代码可能造成的问题。

 

 NETCORE 的三种注入方式

  • Transient: 每一次GetService都会创建一个新的实例
  • Scoped:  在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内)
  • Singleton :整个应用程序生命周期以内只创建一个实例 

 

 

三种注入方式的理解

(1)Singleton 单一实例模式:单一实例对象对每个对象和每个请求都是相同的,可以说是不同客户端不同请求都是相同的。

(2)Transient 暂时性模式:暂时性对象始终不同,无论是不是同一个请求(同一个请求里的不同服务)同一个客户端,每次都是创建新的实例。

(3)Scoped 作用域模式:作用域对象在一个客户端请求中是相同的,但在多个客户端请求中是不同的。(这句是文档的原话,我觉得描述的很清晰)

什么时候用哪种模式?这个不大好说(希望这个可以成为讨论点)

比如一下吧:

1、日志记录器可以实现为单例,因为在整个生命周期内都可以只使用一个实例;

2、数据库访问上下文(DbContext)选择 Scoped 的应该是最佳候选,因为 services.AddDbContext 默认就是 Scoped(哈哈哈);

3、如果需要利用深度依赖关系图(a deep dependency graph)创建惟一对象,则可以考虑将该对象注册为 transient 。

 

 

 

以下举例:

新建三个接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NETCORE.DI.Ope
{
    public interface IOperation
    {
        Guid OpertaionId { get; }
    }


    public interface IOperationSingleton : IOperation
    { }

    public interface IOperationTransient : IOperation
    { }

    public interface IOperationScoped : IOperation
    { }
}

 

 

新建一个 接口实现类 Operation ,实现这三个接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace NETCORE.DI.Ope
{
    public class Operation : IOperationTransient,IOperationScoped,IOperationSingleton
    {
        private Guid _guid;

        public Operation()
        {
            _guid = Guid.NewGuid();
        }

        public Operation(Guid guid)
        {
            _guid = guid;
        }

        public Guid OpertaionId => _guid;
    }
}

 

 

在Startup.cs中 实验三个种注入方式:

在 ConfigureServices  方法中添加如下内容

            //默认构造
            services.AddSingleton<IOperationSingleton, Operation>();

            //自定义传入 空值
            services.AddSingleton<IOperationSingleton>(new Operation(Guid.Empty));

            // 自定义传入一个New的Guid
            services.AddSingleton<IOperationSingleton>(new Operation(Guid.NewGuid()));


            var provider = services.BuildServiceProvider();

            // 输出singletone1的Guid
            var singletone1 = provider.GetService<IOperationSingleton>();
            Console.WriteLine($"signletone1: {singletone1.OpertaionId}");

            // 输出singletone2的Guid
            var singletone2 = provider.GetService<IOperationSingleton>();
            Console.WriteLine($"signletone2: {singletone2.OpertaionId}");
            Console.WriteLine($"singletone1 == singletone2 ? : { singletone1 == singletone2 }");

 

 以上是 Singleton 模式,我们获取到的始终都是我们最后一次注册的那个给了一个Guid的实例,前面的会被覆盖。

 

以下是 Scoped 模式

            services.AddScoped<IOperationScoped, Operation>();

            var provider = services.BuildServiceProvider();

            using (var score1 = provider.CreateScope())
            {
                var p = score1.ServiceProvider;

                var scopeobj1 = p.GetService<IOperationScoped>();

                var scopeobj2 = p.GetService<IOperationScoped>();


                Console.WriteLine($"scope1:{scopeobj1.OpertaionId}");
                Console.WriteLine($"scope2:{scopeobj2.OpertaionId}");
            }


            Console.WriteLine("---------------------------------");

            using (var score1 = provider.CreateScope())
            {
                var p = score1.ServiceProvider;

                var scopeobj1 = p.GetService<IOperationScoped>();

                var scopeobj2 = p.GetService<IOperationScoped>();


                Console.WriteLine($"scope1:{scopeobj1.OpertaionId}");
                Console.WriteLine($"scope2:{scopeobj2.OpertaionId}");
            }

 

Scoped 模式的输出结果:

 

  

 

项目名称:NETCORE.DI

项目地址:https://gitee.com/wuxincaicai/NETCORE.git

 

 

 

 

 

 

二. Scoped 模式的解析

新建项目 NETCORE.DI.Scoped

项目结构

 

 

 

 

新建接口: IOperation

    public interface IOperation
    {
        Guid OperationId { get; }
    }

 

 

 

新建 Operation 类

    public class Operation : IOperation
    {
        private Guid _guid;

        public Operation()
        {
            this._guid = Guid.NewGuid();
        }

        public Guid OperationId => _guid;
    }

 

 

新建 OperationService 服务,以及 DIController.cs 控制器,分别注入  IOperation

    public class OperationService
    {
        private IOperation _ioperation;
        public OperationService(IOperation ioperation)
        {
            _ioperation = ioperation;
        }

        public Guid getgg() => _ioperation.OperationId;
    }

 

    [Route("api/[controller]")]
    [ApiController]
    public class DIController : ControllerBase
    {
        private IOperation _ioperation;

        private OperationService _operationService;

        public DIController(IOperation operation, OperationService operationService)
        {
            _ioperation = operation;

            _operationService = operationService;
        }

        [HttpGet]
        [Route("Getgg")]
        public JsonResult Getgg()
        {
            var opt_g = _ioperation.OperationId;

            var opts_g = _operationService.getgg();

            return new JsonResult(new { controller = opt_g, service = opts_g });
        }
    }

 

 

startup.cs 注入 IOperation 作用域方式。

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddScoped<IOperation, Operation>();
            services.AddTransient<OperationService, OperationService>();
        }

 

 

调用 https://localhost:5001/api/di/getgg

 

 

 

 

项目:NETCORE.DI.Scoped

项目地址:https://gitee.com/wuxincaicai/NETCORE.git

 

 

 

引用:https://www.cnblogs.com/jesse2013/p/di-in-aspnetcore.html

 

posted @ 2020-05-28 14:26  无心々菜  阅读(428)  评论(0编辑  收藏  举报