.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类的 ...
随机推荐
- 基于python中librosa的声音混音实例解析
一 概念 1.一些概念 Librosa是一个用于音频.音乐分析.处理的python工具包,一些常见的时频处理.特征提取.绘制声音图形等功能应有尽有,功能十分强大.本文主要介绍libros的基本用法 ...
- 基于python的固定间隔时间执行实例解析
一 概念 datetime的用法如下: import datetime. # 打印当前时间 time1 = datetime.datetime.now() print(time1) # 打印按指定格式 ...
- websocket服务器的创建
就这上篇文章的代码,我们会继续实现以下websocket的协议. 为什么要使用websocket呢? 它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平 ...
- 《TencentNCNN系列》 之bin文件(网络参数文件)格式分析
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- CAD和实时渲染之间的差距
建筑师如何将他们喜爱的CAD工具与虚幻引擎和Twinmotion 等快速实时渲染工具结合使用 每个建筑师都有自己喜欢的设计工具.从Revit的粉丝到阿奇卡德的狂热用户,AEC专业人员通常首选CAD和B ...
- 三维模型OBJ格式轻量化压缩在移动智能终端应用方面的重要性分析
三维模型OBJ格式轻量化压缩在移动智能终端应用方面的重要性分析 三维模型的OBJ格式轻量化压缩在移动智能终端应用方面具有重要性.以下是对三维模型OBJ格式轻量化压缩在移动智能终端应用方面重要性的分析: ...
- Python实现简易版TCP代理
什么是TCP代理 TCP代理是一种网络代理技术,它允许客户端和服务器之间通过一个位于中间的第三方TCP代理服务器进行通信.TCP代理的工作方式是客户端向代理服务器发送TCP连接请求,代理服务器将此请求 ...
- 基于Python代码的相关性热力图,VIF共线性诊断图及残差四图的使用及解释
注:热力图和共线性诊断图易看易解释,这里不再阐述 残差四图(Residuals vs Fitted Plot,Normal Q-Q Plot,Scale-Location Plot,Cook's Di ...
- Mybatis使用JDBC实现数据库批量添加
1.spring注入数据源 @Resource(name = "dataSource") private DataSource dataSource; 2.连接数据库批量添加 pu ...
- IPv4地址的结构体与网络字节序
IPv4地址的结构体 /* Fixed-size types, underlying types depend on word size and compiler. */ typedef signed ...