控制反转和依赖注入

0x00

之前听过一句话,设计模式是药,不要乱吃……

代码的功能化与模块化。

修改某一部分的代码,不应该导致其他意外的位置出现错误。

依赖注入(Dependency Injection, DI)通常会与控制反转(Inversion of Control, IoC)一同出现,从去年接触了一点框架的时候,才听到这个新鲜东西,说起来,他们其实是一回事。

0x02 IoC

控制反转,是一种设计理念, 是一个设计的原理,他也被叫做好莱坞原则:不要给我们打电话;我们会给你打电话。

0x01 DI

依赖注入就是为了减少模块之间的耦合,

依赖注入是允许从类的外部注入依赖项,因此注入的类只需要实现了必须的功能(通常是接口),这就可是让注入的依赖项独立于对象的创建。

先看一个简单的打印功能的实现,没有使用依赖注入。

1
2
3
4
public class GreetingService
{
public string Greet(string name) => $"Hello, {name}";
}
1
2
3
4
5
6
7
8
public class HomeController
{
public string Hello (string name)
{
var service = new GreetingService();
return service.Greet(name);
}
}
1
2
3
4
5
6
static void Main()
{
var controller = new HomeController();
string result = controller.Hello("Stephanie");
Console.WriteLine(result);
}

如果想要对 HomeController 进行测试,或对实现方式进行修改,都需要对紧密耦合的另一部分进行修改,单独修改是很不容易的。

如果使用依赖注入的方式实现上面的功能:

1
2
3
4
public interface IGreetingService
{
string Greet(string name);
}
1
2
3
4
public class GreetingService : IGreetingService
{
public string Greet(string name) => $"Hello, {name}";
}
1
2
3
4
5
6
7
8
9
public class HomeController
{
private readonly IGreetingService _greetingService;
public HomeController (IGreetingService greetingService)
{
_greetingService = greetingService ?? throw new ArgumentNullException (nameof(greetingService));
}
public string Hello(string name) => _greetingService.Greet(name);
}
1
2
3
4
5
6
static void Main()
{
var controller = new HomeController(new GreetingService());
string result = controller.Hello("Matthias");
Console.WriteLine(result);
}

HomeController 的实现在没有依赖接口 IGreetingService 的具体实现。这是典型的构造函数注入的依赖注入模式。

0xff

挣脱套鹿。