NETCORE - 依赖注入
依赖:当一个类需要另一个类协作来完成工作的时候就产生了依
注入:注入体现的是一个IOC(控制反转的的思想),
private ILoginService<ApplicationUser> _loginService; public AccountController() { _loginService = new EFLoginService() }
大师说,这样不好。你不应该自己创建它,而是应该由你的调用者给你。于是你通过构造函数让外界把这两个依
public AccountController(ILoginService<ApplicationUser> loginService) { _loginService = loginService; }
把依赖的创建丢给其它人,自己只负责使用,其它人丢给你依赖的这个过程理解为注入。
反转?
NETCORE 的三种注入方式
三种注入方式的理解
(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