zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    在CI框架中的配置整合amfphp
    php操作memcache的使用【转】
    notepad++ 快捷键大全
    utf8_general_ci和utf8_unicode_ci的比较
    50个必备的实用jQuery代码段
    强制浏览器下载PDF文件
    Ajax不能接受php return值的原因
    Proftpd mysql认证配置文档
    CI公用模型
    sublime 相关配置和快捷键
  • 原文地址:https://www.cnblogs.com/1285026182YUAN/p/12980616.html
Copyright © 2011-2022 走看看