【ASP.NET Core】ASP.NET Core 依赖注入
1.1依赖
1.2 什么是注入
1
2
3
4
5
|
private ILoginService<ApplicationUser> _loginService;
public AccountController()
{
_loginService = new EFLoginService()
}
|
大师说,这样不好。你不应该自己创建它,而是应该由你的调用者给你。于是你通过构造函数让外界把这两个依赖传给你。
1
2
3
4
5
|
public
AccountController(ILoginService<ApplicationUser> loginService)
{
_loginService = loginService;
}
|
把依赖的创建丢给其它人,自己只负责使用,其它人丢给你依赖的这个过程理解为注入。
1.3 为什么要反转?
var controller = new AccountController(new EFLoginService()); controller.Login(userName, password);// 用Redis来替换原来的EF登录var controller = new AccountController(new RedisLoginService()); controller.Login(userName, password);
1.4 何为容器
- 绑定服务与实例之间的关系
- 获取实例,并对实例进行管理(创建与销毁)
二、.NET Core DI
2.1 实例的注册
- IServiceCollection 负责注册
- IServiceProvider 负责提供实例
var serviceCollection = new ServiceCollection().AddTransient<ILoginService, EFLoginService>().AddSingleton<ILoginService, EFLoginService>().AddScoped<ILoginService, EFLoginService>();
public interface IServiceCollection : IList<ServiceDescriptor> { }
我们上面的AddTransient、AddSignletone和Scoped方法是IServiceCollection的扩展方法, 都是往这个List里面添加ServiceDescriptor。
private static IServiceCollection Add(IServiceCollection collection,Type serviceType,Type implementationType,ServiceLifetime lifetime) {var descriptor = new ServiceDescriptor(serviceType, implementationType, lifetime);collection.Add(descriptor);return collection; }
2.2 实例的生命周期之单例
- Transient: 每一次GetService都会创建一个新的实例
- Scoped: 在同一个Scope内只初始化一个实例 ,可以理解为( 每一个request级别只创建一个实例,同一个http request会在一个 scope内)
- Singleton :整个应用程序生命周期以内只创建一个实例
public enum ServiceLifetime {Singleton,Scoped,Transient }
public interface IOperation {Guid OperationId { get; } } public interface IOperationSingleton : IOperation { } public interface IOperationTransient : IOperation{} public interface IOperationScoped : IOperation{}
我们的 Operation实现很简单,可以在构造函数中传入一个Guid进行赋值,如果没有的话则自已New一个 Guid。
public class Operation : IOperationSingleton,IOperationTransient,IOperationScoped {private Guid _guid;public Operation() {_guid = Guid.NewGuid();}public Operation(Guid guid){_guid = guid;}public Guid OperationId => _guid; }
在程序内我们可以多次调用ServiceProvider的GetService方法,获取到的都是同一个实例。
var services = new ServiceCollection(); // 默认构造 services.AddSingleton<IOperationSingleton, Operation>(); // 自定义传入Guid空值 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.OperationId}");// 输出singletone2的Guid var singletone2 = provider.GetService<IOperationSingleton>(); Console.WriteLine($"signletone2: {singletone2.OperationId}"); Console.WriteLine($"singletone1 == singletone2 ? : { singletone1 == singletone2 }");
我们对IOperationSingleton注册了三次,最后获取两次,大家要注意到我们获取到的始终都是我们最后一次注册的那个给了一个Guid的实例,前面的会被覆盖。
2.3 实例生命周期之Tranisent
这次我们获取到的IOperationTransient为两个不同的实例。
var services = new ServiceCollection(); services.AddTransient<IOperationTransient, Operation>();var provider = services.BuildServiceProvider();var transient1 = provider.GetService<IOperationTransient>(); Console.WriteLine($"transient1: {transient1.OperationId}");var transient2 = provider.GetService<IOperationTransient>(); Console.WriteLine($"transient2: {transient2.OperationId}"); Console.WriteLine($"transient1 == transient2 ? : { transient1 == transient2 }");
2.4 实例生命周期之Scoped
var services = new ServiceCollection() .AddScoped<IOperationScoped, Operation>() .AddTransient<IOperationTransient, Operation>() .AddSingleton<IOperationSingleton, Operation>();
接下来我们用ServiceProvider.CreateScope方法创建一个Scope
var provider = services.BuildServiceProvider(); using (var scope1 = provider.CreateScope()) {var p = scope1.ServiceProvider;var scopeobj1 = p.GetService<IOperationScoped>();var transient1 = p.GetService<IOperationTransient>();var singleton1 = p.GetService<IOperationSingleton>();var scopeobj2 = p.GetService<IOperationScoped>();var transient2 = p.GetService<IOperationTransient>();var singleton2 = p.GetService<IOperationSingleton>();Console.WriteLine($"scope1: { scopeobj1.OperationId }," +$"transient1: {transient1.OperationId}, " +$"singleton1: {singleton1.OperationId}");Console.WriteLine($"scope2: { scopeobj2.OperationId }, " +$"transient2: {transient2.OperationId}, " +$"singleton2: {singleton2.OperationId}"); }
接下来
scope1: 200d1e63-d024-4cd3-88c9-35fdf5c00956,
transient1: fb35f570-713e-43fc-854c-972eed2fae52,
singleton1: da6cf60f-670a-4a86-8fd6-01b635f74225scope2: 200d1e63-d024-4cd3-88c9-35fdf5c00956, transient2: 2766a1ee-766f-4116-8a48-3e569de54259, singleton2: da6cf60f-670a-4a86-8fd6-01b635f74225
如果再创建一个新的Scope运行,
scope1: 29f127a7-baf5-4ab0-b264-fcced11d0729,
transient1: 035d8bfc-c516-44a7-94a5-3720bd39ce57,
singleton1: da6cf60f-670a-4a86-8fd6-01b635f74225scope2: 29f127a7-baf5-4ab0-b264-fcced11d0729, transient2: 74c37151-6497-4223-b558-a4ffc1897d57, singleton2: da6cf60f-670a-4a86-8fd6-01b635f74225
三、DI在ASP.NET Core中的应用
3.1在Startup类中初始化
public void ConfigureServices(IServiceCollection services) {services.AddTransient<ILoginService<ApplicationUser>, EFLoginService>();services.AddMvc(); )
ASP.NET Core的一些组件已经提供了一些实例的绑定,像AddMvc就是Mvc Middleware在 IServiceCollection上添加的扩展方法。
public static IMvcBuilder AddMvc(this IServiceCollection services) {if (services == null){throw new ArgumentNullException(nameof(services));}var builder = services.AddMvcCore();builder.AddApiExplorer();builder.AddAuthorization();AddDefaultFrameworkParts(builder.PartManager);... }
3.2 Controller中使用
private ILoginService<ApplicationUser> _loginService; public AccountController(ILoginService<ApplicationUser> loginService) {_loginService = loginService; }
我们只要在控制器的构造函数里面写了这个参数,ServiceProvider就会帮我们注入进来。这一步是在Mvc初始化控制器的时候完成的,我们后面再介绍到Mvc的时候会往细里讲。
3.3 View中使用
@using MilkStone.Services; @model MilkStone.Models.AccountViewModel.LoginViewModel @inject ILoginService<ApplicationUser> loginService <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head></head> <body>@loginService.GetUserName() </body> </html>
3.4 通过 HttpContext来获取实例
HttpContext.RequestServices.GetService<ILoginService<ApplicationUser>>();
四、如何替换其它的Ioc容器
builder.RegisterGeneric(typeof(LoggingBehavior<,>)).As(typeof(IPipelineBehavior<,>));builder.RegisterGeneric(typeof(ValidatorBehavior<,>)).As(typeof(IPipelineBehavior<,>));
这会给我们的初始化带来一些便利性,我们来看看如何替换Autofac到ASP.NET Core。我们只需要把Startup类里面的 ConfigureService的 返回值从 void改为 IServiceProvider即可。而返回的则是一个AutoServiceProvider。
public IServiceProvider ConfigureServices(IServiceCollection services){services.AddMvc();// Add other framework services// Add Autofacvar containerBuilder = new ContainerBuilder();containerBuilder.RegisterModule<DefaultModule>();containerBuilder.Populate(services);var container = containerBuilder.Build();return new AutofacServiceProvider(container); }
4.1 有何变化
【ASP.NET Core】ASP.NET Core 依赖注入相关推荐
- ASP.NET Core Filter如何支持依赖注入
概述 通过使用 ASP.NET Core 中的筛选器,可在请求处理管道中的特定阶段之前或之后运行代码.内置筛选器处理任务,例如:授权(防止用户访问未获授权的资源).响应缓存(对请求管道进行短路出路,以 ...
- ASP.NET Core技术研究-探秘依赖注入框架
ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务.提供服务.依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者. 毫不夸张的说,ASP.NET ...
- [ASP.NET Core 3框架揭秘] 依赖注入:依赖注入模式
IoC主要体现了这样一种设计思想:通过将一组通用流程的控制权从应用转移到框架之中以实现对流程的复用,并按照"好莱坞法则"实现应用程序的代码与框架之间的交互.我们可以采用若干设计模式 ...
- 依赖注入的三种方式_ASP.NET Core技术研究-探秘依赖注入框架
ASP.NET Core在底层内置了一个依赖注入框架,通过依赖注入的方式注册服务.提供服务.依赖注入不仅服务于ASP.NET Core自身,同时也是应用程序的服务提供者. 毫不夸张的说,ASP.NET ...
- ASP.NET Core中如影随形的”依赖注入”[上]: 从两个不同的ServiceProvider说起
我们一致在说 ASP.NET Core广泛地使用到了依赖注入,通过前面两个系列的介绍,相信读者朋友已经体会到了这一点.由于前面两章已经涵盖了依赖注入在管道构建过程中以及管道在处理请求过程的应用,但是内 ...
- ASP.NET CORE 第四篇 依赖注入IoC学习 + AOP界面编程初探
原文作者:老张的哲学 更新 1.如果看不懂本文,或者比较困难,先别着急问问题,我单写了一个关于依赖注入的小Demo,可以下载看看,多思考思考注入的原理: https://github.com/anjo ...
- Asp.Net.Core 系列-中间件和依赖注入进阶篇
上一节讲了中间件和依赖注入的基础,紧接着: 中间件是怎么使用的?使用步骤是什么? 只要把中间件注册到管道中就行了,可以借助Startup对象(DelegateStartup或者ConventionBa ...
- Asp.net Core 自带DI依赖注入
一.新增依赖注入类DIIoc /// <summary>/// DI依赖注入/// </summary>public class DIIoc{public static voi ...
- .net core精彩实例分享 -- 依赖注入和中间件
文章目录 介绍 具体案例 临时访问服务 以委托形式定义中间件 带参数中间件 IMiddleware中间件的用途 让 HTTP 管道"短路" 中间件的分支映射 文件服务 总结 介绍 ...
- .NET CORE——Console中使用依赖注入
我们都知道,在 ASP.NET CORE 中通过依赖注入的方式来使用服务十分的简单,而在 Console 中,其实也只是稍微绕了个小弯子而已.不管是内置 DI 组件或者第三方的 DI 组件(如Auto ...
最新文章
- 行业观察 | 全球IoT云平台第一股诞生,IoT离爆发还有多远?
- 分布式 Socket 通信
- 如何切换默认python版本_Debian中如何切换默认Python版本
- FTP在aliyun上使用经验
- springboot jpa sql打印_SpringBoot集成Spring Data JPA以及读写分离
- CIKONSS-纯CSS实现的响应式Icon
- 悲哀!面试现场,简单几道java算法题,90%程序员没写出来
- 利用selenium模块配合chromedriver把html文件转换为图片
- Spring定时任务@scheduled多线程的使用(@Async注解)
- python卸载_微软再出神器,这次终于对Python下手了!
- 《游戏学习》java实现连珠五子棋完整代码
- 超高频RFID智慧酒店管理系统解决方案
- 基金投资入门 5:基金的业务类型及交易中的费用
- cpu上干硅脂怎么清理_如何去除CPU上原来的硅脂
- springCloud-Eureka自我保护模式
- coso2dx-lua 电脑模拟器 , 不重启游戏 直接让修改过的 lua 代码 生效
- winform使用多线程时跨线程访问控件
- Strange Fractions(奇怪的分数)-数论
- php简易留言板功能,PHP实现简单留言板功能的方法
- 全球5G设备商最新排名