.net core的依赖注入学习
依赖注入(Dependency Injection,DI),简称DI,它可以降低各模块之间的耦合
首先需要安装两个Nuget包:
Microsoft.Extensions.DependencyInjection
Microsoft.Extensions.DependencyInjection.Abstractions
安装完之后要在主程序里面引用第一个包
using Microsoft.Extensions.DependencyInjection
提前准备好一个接口和两个实现类
public interface ITestService
{
public string Name { get; set; }
public void SayHi();
}
public class TestServiceImpl : ITestService
{
public string Name { get; set; }
public void SayHi()
{
Console.WriteLine($"Hi, I'm {Name}");
}
}
public class TestServiceImpl2 : ITestService
{
public string Name { get; set; }
public void SayHi()
{
Console.WriteLine($"你好,我是{Name}");
}
}
然后在主程序中调用,以下是一个服务从注册到被使用的代码
//首先声明一个容器服务的对象,将其命名为services
//然后将需要被注册服务的对象TestServiceImpl添加放入容器服务对象services中
//添加方式有三种
//services.AddTransient
//services.AddSingleton
//services.AddScoped
//添加完服务之后使用services.BuildServiceProvider()方法构造出服务容器sp
//使用sp.GetService<TestServiceImpl>()即可使用刚刚添加进去的TestServiceImpl,如果没有对象被添加进服务,则是Null;
//sp.GetRequiredService,如果没有对象被添加进服务则会抛异常
//如果注册了多个服务,使用的是GetService,那么实际上选择的是最后一个服务(此处未体现)
ServiceCollection services = new ServiceCollection();
//services.AddTransient<TestServiceImpl>();
//services.AddSingleton<TestServiceImpl>();
services.AddScoped<TestServiceImpl>();
using (ServiceProvider sp = services.BuildServiceProvider())
{
TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
testService.Name = "tom";
testService.SayHi();
}
关于三种添加方式AddTransient(瞬态),AddSingleton(单例),AddScoped(范围);
使用AddTransient添加到服务的对象,每一次获取服务sp.GetService都是新的
而使用AddSingleton添加到服务的对象,每一次获取服务sp.GetService都是原来的
ServiceCollection services = new ServiceCollection();
services.AddTransient<TestServiceImpl>();
services.AddSingleton<TestServiceImpl2>();
using (ServiceProvider sp = services.BuildServiceProvider())
{
//使用AddTransient添加的
/*输出结果:
Hi, I'm xiaoli
False
Hi, I'm dali
Hi, I'm xiaoli
*/
TestServiceImpl t1 = sp.GetService<TestServiceImpl>();
t1.Name = "xiaoli";
t1.SayHi();
TestServiceImpl t2 = sp.GetService<TestServiceImpl>();
Console.WriteLine(object.ReferenceEquals(t1,t2));
t2.Name = "dali";
t2.SayHi();
t1.SayHi();
//使用AddSingleton添加的
/*输出结果:
你好,我是xiaoli
True
你好,我是dali
你好,我是dali*/
TestServiceImpl2 tt1 = sp.GetService<TestServiceImpl2>();
tt1.Name = "xiaoli";
tt1.SayHi();
TestServiceImpl2 tt2 = sp.GetService<TestServiceImpl2>();
Console.WriteLine(object.ReferenceEquals(tt1, tt2));
tt2.Name = "dali";
tt2.SayHi();
tt1.SayHi();
}
如果使用的是AddScoped,并且还限定了范围,那么在同一个范围内每次获取到的对象都是一样的
ServiceCollection services = new ServiceCollection();
services.AddScoped<TestServiceImpl>();
using (ServiceProvider sp = services.BuildServiceProvider())
{
TestServiceImpl tt1;
//在iss中获取Scope相关对象,iss1.ServiceProvider,而不是sp
using (IServiceScope iss1 = sp.CreateScope())
{
TestServiceImpl t1 = iss1.ServiceProvider.GetService<TestServiceImpl>();
t1.Name = "xiaoli";
t1.SayHi();
TestServiceImpl t2 = iss1.ServiceProvider.GetService<TestServiceImpl>();
Console.WriteLine(object.ReferenceEquals(t1, t2));
Console.WriteLine(t1.GetType());
tt1 = t1;
}
using (IServiceScope iss2 = sp.CreateScope())
{
TestServiceImpl t1 = iss2.ServiceProvider.GetService<TestServiceImpl>();
t1.Name = "xiaoli";
t1.SayHi();
TestServiceImpl t2 = iss2.ServiceProvider.GetService<TestServiceImpl>();
//true 同一个范围内的对象相同
Console.WriteLine(object.ReferenceEquals(t1, t2));
//false,两个范围(scope)的对象不相同
Console.WriteLine(object.ReferenceEquals(tt1, t2));
}
}
/*
Hi, I'm xiaoli
True
ioc1.TestServiceImpl
Hi, I'm xiaoli
True
False
*/
生命周期的选择:如果类无状态,建议为Singleton;如果类有状态,且有Scope控制,建议为Scoped,因为通常这种Scope控制下的代码都是运行在同一个线程中的,没有并发修改的问题;在使用Transient的时候要谨慎。
简单应用:
创建3个接口和对应的实现类,再建一个服务容器类
//日志信息
interface ILog
{
public void Log(string msg);
}
class LogImpl : ILog
{
public void Log(string msg)
{
Console.WriteLine($"日志信息:{msg}");
}
}
//配置信息
interface IConfig
{
public string GetValue(string name);
}
class ConfigImpl : IConfig
{
public string GetValue(string name)
{
return "Hello";
}
}
//保存信息
interface IStorage
{
public void Save(string content, string name);
}
class StorageImpl : IStorage
{
private readonly IConfig config;
public StorageImpl(IConfig config)
{
this.config = config;
}
public void Save(string content, string name)
{
string server = config.GetValue("server");
Console.WriteLine($"向服务器:{server}的文件名为:{name}上传{content}");
}
}
//服务容器
class Controller
{
private readonly ILog log;
private readonly IStorage storage;
public Controller(ILog log, IStorage storage)
{
this.log = log;
this.storage = storage;
}
public void Test()
{
log.Log("开始上传");
storage.Save("4646461jhk", "1.txt");
log.Log("上传完毕");
}
}
在主函数中实现
static void Main(string[] args)
{
ServiceCollection services = new ServiceCollection();
services.AddScoped<Controller>();
services.AddScoped<ILog, LogImpl>();
services.AddScoped<IStorage, StorageImpl>();
services.AddScoped<IConfig, ConfigImpl>();
using(ServiceProvider sp = services.BuildServiceProvider())
{
var c = sp.GetRequiredService<Controller>();
c.Test();
}
Console.ReadKey();
}
/*输出结果
日志信息:开始上传
向服务器:Hello的文件名为:1.txt上传4646461jhk
日志信息:上传完毕
*/
学习来自杨中科大佬在某站上面的视频
.net core的依赖注入学习的更多相关文章
- ASP.NET Core之依赖注入
本文翻译自:http://www.tutorialsteacher.com/core/dependency-injection-in-aspnet-core ASP.NET Core支持依赖注入,依赖 ...
- 【半小时大话.net依赖注入】(下)详解AutoFac+实战Mvc、Api以及.NET Core的依赖注入
系列目录 上|理论基础+实战控制台程序实现AutoFac注入 下|详解AutoFac+实战Mvc.Api以及.NET Core的依赖注入 前言 本来计划是五篇文章的,每章发个半小时随便翻翻就能懂,但是 ...
- 几十行代码实现ASP.NET Core自动依赖注入
在开发.NET Core web服务的时候,我们习惯使用自带的依赖注入容器来进行注入. 于是就会经常进行一个很频繁的的重复动作:定义一个接口->写实现类->注入 有时候会忘了写Add这一步 ...
- 重新整理 .net core 实践篇————依赖注入应用[二]
前言 这里介绍一下.net core的依赖注入框架,其中其代码原理在我的另一个整理<<重新整理 1400篇>>中已经写了,故而专门整理应用这一块. 以下只是个人整理,如有问题, ...
- 【ASP.NET Core】依赖注入高级玩法——如何注入多个服务实现类
依赖注入在 ASP.NET Core 中起中很重要的作用,也是一种高大上的编程思想,它的总体原则就是:俺要啥,你就给俺送啥过来.服务类型的实例转由容器自动管理,无需我们在代码中显式处理. 因此,有了依 ...
- .Net Core 通过依赖注入和动态加载程序集实现宿程序和接口实现类库完全解构
网上很多.Net Core依赖注入的例子代码,例如再宿主程序中要这样写: services.AddTransient<Interface1, Class1>(); 其中Interface1 ...
- .NET Core的依赖注入[1]: 控制反转
写在前面:我之前写过一系列关于.NET Core依赖注入的文章,由于.NET Core依赖注入框架的实现原理发生了很大的改变,加上我对包括IoC和DI这些理论层面的东西又有了一些新的理解,所以我在此基 ...
- .NET Core 中依赖注入 AutoMapper 小记
最近在 review 代码时发现同事没有像其他项目那样使用 AutoMapper.Mapper.Initialize() 静态方法配置映射,而是使用了依赖注入 IMapper 接口的方式 servic ...
- 用工厂模式解决ASP.NET Core中依赖注入的一个烦恼
这是最近在实际开发中遇到的一个问题,用 asp.net core 开发一个后端 web api ,根据指定的 key 清除 2 台 memcached 服务器上的缓存.背景是我们在进行 .net co ...
- .Net Core 使用依赖注入
ASP.NET Core 源码阅读笔记(1) ---Microsoft.Extensions.DependencyInjection 在asp .net中使用依赖注入很简单,只需要在Startup类的 ...
随机推荐
- 关于Jitpack发布aar,会丢失内置依赖库问题
原文:关于Jitpack发布aar,会丢失内置依赖库问题 | Stars-One的杂货小窝 关于发布aar出现的一个大坑排查,折腾了两天,终于是找到了解决方案 问题描述 有这样的一个情况,我新建了个A ...
- springboot如何优雅的获取前端参数
写在前面 对于初学者来说,困难的不是理论知识,而是如何在程序中具体实现. 现在的项目基本上都是前后端分离的项目,如何打通前后端,接收前端传过来的参数呢? 废话不多说,这篇文章就来说一说接收前端参数的具 ...
- [深度学习] 计算机视觉低代码工具Supervision库使用指北
Supervision库是一款出色的Python计算机视觉低代码工具,其设计初衷在于为用户提供一个便捷且高效的接口,用以处理数据集以及直观地展示检测结果.Supervision库的官方开源仓库地址为: ...
- apache添加php模块
实验介绍: apache本身只能发布静态网站,而添加了php模块就可以发布动态网站 一:下载php 进入php官方网址https://www.php.net/ 点击进入windows版本 下载thre ...
- 三维模型3DTile格式轻量化的数据压缩与性能平衡关系分析
三维模型3DTile格式轻量化的数据压缩与性能平衡关系分析 对于三维模型的3DTile格式轻量化处理,数据压缩和性能之间的平衡关系是一个重要的考虑因素.以下是这两者关系的详细分析: 1.数据压缩与加载 ...
- linux查看域名对应的解析ip
方法1-直接使用ping 方法2-nslookup 方法3-dig
- 浅谈分布式任务调度系统Celery的设计与实现
Celery是一个简单.灵活且可靠的分布式任务队列,它支持任务的异步执行.进度监控.重试机制等功能. Celery的核心组件包括: Broker:消息中间件,如RabbitMQ.用于任务的发布和订阅. ...
- Oracle 已存在数据的大表 改 分区表
创建表,插入测试数据 -- Create table create table LXW_TEST ( CDATE DATE, T1 NUMBER, T2 VARCHAR2(2) ) ; insert ...
- read IEEE Standard for verilog(1)
IEEE Standard for Verilog Hardware Description Language 英语说明阅读,首先看导读.目录.摘要等内容. 摘要: 1 Abstract: The V ...
- KingbaseESV8R6识别IO使用率过高
前言 数据库正常运行离不开I/O的使用,在操作系统上,I/O又离不开存储的性能及使用方式,我们可以在存储层利用raid条带化技术使IOPS达到最佳性能. 本篇文章有助于确认数据库I/O使用率过高的原因 ...