ASP.NET Core 依赖注入
来源:互联网 发布:淘宝店铺改名字 编辑:程序博客网 时间:2024/06/10 19:56
1.1依赖
1.2 什么是注入
private ILoginService<ApplicationUser> _loginService;public AccountController(){ _loginService = new EFLoginService()}
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 实例的注册
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 实例的生命周期之单例
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的Guidservices.AddSingleton <IOperationSingleton>( new Operation(Guid.NewGuid()));var provider = services.BuildServiceProvider();// 输出singletone1的Guidvar singletone1 = provider.GetService<IOperationSingleton>();Console.WriteLine($"signletone1: {singletone1.OperationId}");// 输出singletone2的Guidvar 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 Autofac var 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 2.0 依赖注入
- ASP.NET Core 2.0 依赖注入
- [.NET开发] ASP.NET Core 1.0基础之依赖注入
- Asp.net core 学习笔记--(1)依赖注入
- ASP.NET Core MVC 控制器创建与依赖注入
- ASP.NET Core依赖注入解读&使用Autofac替代实现
- asp.net core 全局注入
- NET Core 三层架构,依赖注入
- .net core依赖注入的封装
- ASP.NET Core中的依赖注入(1):控制反转(IoC)
- ASP.NET Core依赖注入解读&使用Autofac替代实现
- 学习ASP.NET Core,你必须了解无处不在的“依赖注入”
- ASP.NET Core 中的依赖项管理
- asp.net mvc controller 依赖注入入门
- ASP.NET MVC 的依赖注入
- asp.net mvc5 Autofac 依赖注入
- CodeForces
- 在Linux下怎样让top命令启动之后就按内存使用排序(或CPU使用排序)?
- VMware12+ubuntu16+c270 linux上使用摄像头
- 双链表的尾插法建立输出
- android进阶-surfaceView的分析和使用
- ASP.NET Core 依赖注入
- 树形dp小结——2
- 1056. 组合数的和(15)
- 机器学习周志华第一章
- JavaScript学习笔记整理(八)闭包未完
- Python2和Python3的区别
- zabbix安装
- 初识JVM垃圾回收
- POJ 1700非原创