全面理解 ASP.NET Core 依赖注入
一、什么是依赖注入
- 1.1 依赖
- 1.2 什么注入
- 为什么反转
- 何为容器
二、.NET Core DI
- 2.1 实例的注册
- 2.2 实例生命周期之单例
- 2.3 实例生命周期之Tranisent
- 2.4 实例生命周期之Scoped
三、DI在ASP.NET Core中的应用
- 3.1 在Startup类中初始化
- 3.2 Controller中使用
- 3.3 View中使用
- 3.4 通过HttpContext来获取
四、如何替换其它的Ioc容器
一、什么是依赖注入(Denpendency Injection)
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 为什么要反转?
1
2
3
4
5
|
public
AccountController(ILoginService<ApplicationUser> loginService)
{
_loginService = loginService;
}
|
// 用Redis来替换原来的EF登录 var controller = new AccountController(new RedisLoginService()); controller.Login(userName, password);
1.4 何为容器
- 绑定服务与实例之间的关系
- 获取实例,并对实例进行管理(创建与销毁)
二、.NET Core DI
2.1 实例的注册
- IServiceCollection 负责注册
- IServiceProvider 负责提供实例
1
2
3
4
|
var serviceCollection = new ServiceCollection()
.AddTransient<ILoginService, EFLoginService>()
.AddSingleton<ILoginService, EFLoginService>()
.AddScoped<ILoginService, EFLoginService>();
|
1
2
3
|
public interface IServiceCollection : IList<ServiceDescriptor>
{
}
|
我们上面的AddTransient、AddSignletone和Scoped方法是IServiceCollection的扩展方法, 都是往这个List里面添加ServiceDescriptor。
1
2
3
4
5
6
7
8
9
10
11
|
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 :整个应用程序生命周期以内只创建一个实例
1
2
3
4
5
6
|
public enum ServiceLifetime
{
Singleton,
Scoped,
Transient
}
|
1
2
3
4
5
6
7
|
public interface IOperation
{
Guid OperationId { get ; }
}
public interface IOperationSingleton : IOperation { }
public interface IOperationTransient : IOperation{}
public interface IOperationScoped : IOperation{}
|
我们的 Operation实现很简单,可以在构造函数中传入一个Guid进行赋值,如果没有的话则自已New一个 Guid。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
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方法,获取到的都是同一个实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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为两个不同的实例。
2.4 实例生命周期之Scoped
1
2
3
4
|
var services = new ServiceCollection()
.AddScoped<IOperationScoped, Operation>()
.AddTransient<IOperationTransient, Operation>()
.AddSingleton<IOperationSingleton, Operation>();
|
接下来我们用ServiceProvider.CreateScope方法创建一个Scope
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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-01b635f74225 scope2: 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-01b635f74225 scope2: 29f127a7-baf5-4ab0-b264-fcced11d0729, transient2: 74c37151-6497-4223-b558-a4ffc1897d57, singleton2: da6cf60f-670a-4a86-8fd6-01b635f74225
三、DI在ASP.NET Core中的应用
3.1在Startup类中初始化
1
2
3
4
5
6
|
public void ConfigureServices(IServiceCollection services)
{
services.AddTransient<ILoginService<ApplicationUser>,
EFLoginService>();
services.AddMvc();
)
|
ASP.NET Core的一些组件已经提供了一些实例的绑定,像AddMvc就是Mvc Middleware在 IServiceCollection上添加的扩展方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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中使用
1
2
3
4
5
6
|
private ILoginService<ApplicationUser> _loginService;
public AccountController(
ILoginService<ApplicationUser> loginService)
{
_loginService = loginService;
}
|
我们只要在控制器的构造函数里面写了这个参数,ServiceProvider就会帮我们注入进来。这一步是在Mvc初始化控制器的时候完成的,我们后面再介绍到Mvc的时候会往细里讲。
3.3 View中使用
1
2
3
4
5
6
7
8
9
10
|
@ 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来获取实例
1
|
HttpContext.RequestServices.GetService<ILoginService<ApplicationUser>>();
|
四、如何替换其它的Ioc容器
1
2
3
|
builder.RegisterGeneric( typeof (LoggingBehavior<,>)).As( typeof (IPipelineBehavior<,>));
builder.RegisterGeneric( typeof (ValidatorBehavior<,>)).As( typeof (IPipelineBehavior<,>));
|
这会给我们的初始化带来一些便利性,我们来看看如何替换Autofac到ASP.NET Core。我们只需要把Startup类里面的 ConfigureService的 返回值从 void改为 IServiceProvider即可。而返回的则是一个AutoServiceProvider。
1
2
3
4
5
6
7
8
9
10
11
12
|
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 有何变化
转载于:https://www.cnblogs.com/xtjatswc/p/10274725.html
全面理解 ASP.NET Core 依赖注入相关推荐
- 深入理解ASP.NET Core依赖注入
概述 ASP.NET Core可以说是处处皆注入,本文从基础角度理解一下原生DI容器,及介绍下怎么使用并且如何替换官方提供的默认依赖注入容器. 什么是依赖注入 百度百科中对于依赖注入的定义:控制反转( ...
- core控制器属性注入的用处_理解 ASP.NET Core 依赖注入
DI在.NET Core里面被提到了一个非常重要的位置,介绍一下.NET Core的DI实现以及对实例生命周期的管理,在控制台以及Mvc下如何使用DI,以及如何把默认的Service Contain ...
- ASP.NET Core依赖注入深入讨论
这篇文章我们来深入探讨ASP.NET Core.MVC Core中的依赖注入,我们将示范几乎所有可能的操作把依赖项注入到组件中. 依赖注入是ASP.NET Core的核心,它能让您应用程序中的组件增强 ...
- ASP.NET Core依赖注入最佳实践,提示技巧
分享翻译一篇Abp框架作者(Halil İbrahim Kalkan)关于ASP.NET Core依赖注入的博文. 在本文中,我将分享我在ASP.NET Core应用程序中使用依赖注入的经验和建议. ...
- ASP.NET Core依赖注入容器中的动态服务注册
介绍 在ASP.NET Core中,每当我们将服务作为依赖项注入时,都必须将此服务注册到ASP.NET Core依赖项注入容器.但是,一个接一个地注册服务不仅繁琐且耗时,而且容易出错.因此,在这里,我 ...
- 【ASP.NET Core】ASP.NET Core 依赖注入
一.什么是依赖注入(Denpendency Injection) 这也是个老身常谈的问题,到底依赖注入是什么? 为什么要用它? 初学者特别容易对控制反转IOC(Iversion of Control) ...
- core控制器属性注入的用处_了解ASP.NET Core 依赖注入,看这篇就够了
DI在.NET Core里面被提到了一个非常重要的位置, 这篇文章主要再给大家普及一下关于依赖注入的概念,身边有工作六七年的同事还个东西搞不清楚.另外再介绍一下.NET Core的DI实现以及对实例 ...
- ASP.NET Core依赖注入初识与思考
一.前言 在上一篇中,我们讲述了什么是控制反转(IoC)以及通过哪些方式实现的.这其中,我们明白了,「控制反转(IoC)」 是一种软件设计的模式,指导我们设计出更优良,更具有松耦合的程序,而具体的实现 ...
- ASP.NET Core 依赖注入-集成 Autofac
概述 ASP.NET Core 支持依赖关系注入 (DI) 软件设计模式,这是一种在类及其依赖关系之间实现控制反转 (IoC) 的技术. 默认服务容器是 Microsoft.Extensions.De ...
最新文章
- Tensorflow |(1)初识Tensorflow
- SQLite注意以下几点
- Spring Boot集成CKFinder
- elasticsearch-1.3.0 之索引代码粗略梳理
- python喜马拉雅收费_python抓取喜马拉雅免费专辑
- java swing 动态生成表格_6 个曾经牛逼哄哄的 Java 技术,你用过吗?
- Qt工作笔记-QTabWidget插入widget(重要的是编程思想)
- 线段树——操作格子(蓝桥杯试题集)
- access2007连接oracle数据库(通过ODBC)
- 关于Chrome内核88版本无法正常使用Adobe Flash Player公告
- spring基础--bean
- 把字符串复制到剪贴板
- soc设计方法与实现_冷轧钢板局部激光热处理实现汽车轻量化设计新方法
- dubbo 学习资料
- 高层建筑电气设计说明书
- MC34063降压电路
- php加密---六种加密方式
- 老年人微信教程手绘版|微信入门教程1
- 怎么用计算机美元和人民币怎么换算,美金换算人民币计算器(人民币和美元换算)...
- 华为鸿蒙系统老手机能用吗_华为使用自家“鸿蒙”系统,旧手机的安卓系统可以更新成那个系统吗?...
热门文章
- What is Type in managed heap?
- python代码块使用缩进表示-Python 为什么抛弃累赘的花括号,使用缩进来划分代码块?...
- winpython使用教程-Win系统PyQt5安装和使用教程
- python学哪个版本-Python学习,要选哪个版本?
- python画双折线图-Python Pandas 时间序列双轴折线图
- 如何使用python画折线图-Python 使用 matplotlib 画折线图教程
- python语音播报-使用pyttsx3实现python语音播报
- python切片语法-彻底搞懂Python切片操作
- 零基础自学python看什么书-零基础学习Python那些书值得看
- python培训班排行榜-西安Python培训班排行榜