什么是依赖关系注入?

依赖关系注入是控制反转 (IoC) 模式的专用版本,其中要反转的问题是获取所需依赖项的过程。 使用依赖关系注入时,另一个类负责在运行时将依赖项注入对象。

案例

记录日志功能,先记录到控制台,再记录到物理文件,对比改造过程;

面向对象的实现

1
2
3
4
5
6
7
public class ConsoleLogger
{
public void Write(string msg)
{
Console.WriteLine(msg);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Account
{
public void Login()
{
//登录逻辑的实现
//...
ConsoleLogger logger = new ConsoleLogger();
logger.Write("登录中的日志....");
}
public void Logout()
{
//登出逻辑的实现
//...
ConsoleLogger logger = new ConsoleLogger();
logger.Write("登出中的日志....");
}
}

改造方案:需要把所有的 ConsoleLogger logger = new ConsoleLogger(); 替换掉
缺点:

  1. 工作量大
  2. 重复性动作
  3. 代码改动位置多,都需要重新测试

面向接口+工厂模式的实现

1
2
3
4
public interface ILogger
{
void Write(string msg);
}
1
2
3
4
5
6
7
public class ConsoleLogger : ILogger
{
public void Write(string msg)
{
Console.WriteLine(msg);
}
}
1
2
3
4
5
6
7
public class LoggerFactory
{
public static ILogger CreateLogger()
{
return new ConsoleLogger();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Account
{
public void Login()
{
//登录逻辑
//...
ILogger logger = LoggerFactory.CreateLogger();
logger.Write("登录中的日志....");
}
public void Logout()
{
//登出逻辑
//...
ILogger logger = LoggerFactory.CreateLogger();
logger.Write("登出中的日志....");
}
}

改造方案:需要把 LoggerFactory.CreateLogger 中的 new ConsoleLogger(); 替换掉
缺点:

  1. 每个类都需要实现自己的工厂模式,不利于维护

依赖注入实现

Microsoft.Extensions.DependencyInjection

1
2
3
4
public interface ILogger
{
void Write(string msg);
}
1
2
3
4
5
6
7
public class ConsoleLogger : ILogger
{
public void Write(string msg)
{
Console.WriteLine(msg);
}
}
1
2
3
4
5
6
7
IServiceCollection serviceCollection =   new ServiceCollection();
serviceCollection.AddScoped<ILogger, ConsoleLogger>();
using (ServiceProvider serviceProvider = serviceCollection.BuildServiceProvider())
{
ILogger logger = serviceProvider.GetService<ILogger>();
logger.Write("我是日志内容...");
}