什么是依赖注入(DI)和DI容器?
Microsoft依赖项注入容器只是一组类,它们组合到一个代码库中,这个库会自动创建并管理程序中需要的对象。
使用依赖注入目的
是为了解耦。说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用。
这样做的好处就是如果添加了另一个实现类,不需要修改之前代码,只需要修改注入的地方将实现类替换。上面说的通过接口调用方法,实际上还是需要去实例化接口的实现类,只不过不需要我们手动new 构造实现类,而是交给如微软的DI、Autofac这些工具去构建实现类。我们只需要告诉它们,某个类是某个接口的实现类,当用到的时候,工具(比如,微软的DI)会自动通过构造函数实例化类。
依赖的服务如何注入
在Startup文件中通过ConfigureServices方法注入服务
.NET Core 中自带的DI容器
使用容器的好处,由容器来统一管理实例的创建和销毁,你只需要关心怎么用就行了,不需要关系怎么创建跟销毁。
当然容器创建的实例都是有生命周期的。三种创建方法创建的实例生命周期不一样。
- Transient: 瞬态模式,每一次访问 都会创建一个新的实例
- Scoped: 域模式,在同一个Scope内只初始化一个实例 ,可以理解为( 比如在
Asp.Net Core
应用程序中一次请求相当于一个Scoped
)。对象在一次请求中是相同的,但在不同请求中是不同的。 - Singleton :单例模式,整个应用程序生命周期以内只创建一个实例,全局唯一实例
使用 依赖注入(Dependency Injection)
引入NuGet包
Install-Package Microsoft.Extensions.DependencyInjection
实例
/// <summary>
/// 入口
/// </summary>
public void Run()
{
//注册服务
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}]---注册服务");
ServiceCollection services = new ServiceCollection();
services.AddScoped<Controller>();
services.AddScoped<IFileLog, FileLogService>();
services.AddScoped<IConfig, ConfigService>();
using (var sp = services.BuildServiceProvider())
{
try
{
// var c = sp.GetRequiredService<Controller>();
var c = sp.GetService<Controller>();
if (c != null)
{
c.Test();
}
}
catch (Exception ex)
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}]-异常" + ex.Message);
}
}
}
class Controller
{
private readonly IFileLog log;
public Controller(IFileLog log)
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}]---Controller--构造函数");
this.log = log;
}
public void Test()
{
//业务逻辑
this.log.Log($"[{Thread.CurrentThread.ManagedThreadId}]---xxxxxxxx日志内容xxxxx", "a.txt");
}
}
interface IConfig
{
public string GetValue(string key);
}
class ConfigService : IConfig
{
public string GetValue(string key)
{
//到配置文件读取 key-value 配置
return key;
}
}
interface IFileLog
{
public void Log(string message, string txtName);
}
class FileLogService : IFileLog
{
private readonly IConfig config;
public FileLogService(IConfig config)
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}]---FileLogService--构造函数");
this.config = config;
}
public void Log(string message, string txtName)
{
var value = config.GetValue("D盘");
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}]---向({value}/{txtName})文件,写入{message}");
}
}