依赖注入是什么
依赖注入(Dependency Injection),简称DI,类之间的依赖关系由容器来负责。
简单来讲a依赖b,但a不创建(或销毁)b,仅使用b,b的创建(或销毁)交给容器。
引入依赖注入的目的是为了解耦。说白了就是面向接口编程,通过调用接口的方法,而不直接实例化对象去调用。
这样做的好处就是如果添加了另一个实现类,不需要修改之前代码,只需要修改注入的地方将实现类替换。
上面说的通过接口调用方法,实际上还是需要去实例化接口的实现类,只不过不需要我们手动new 构造实现类,
而是交给如微软的DI、Autofac这些工具去构建实现类。我们只需要告诉它们,某个类是某个接口的实现类,
当用到的时候,工具(比如,微软的DI)会自动通过构造函数实例化类。
a只是去使用b,并不去创建b,从而降低代码的耦合性
代码耦合性过高
首先有一个小明,它可以杀怪
namespace NoInjection.ConsoleApp
{
public class Actor
{
private string name = "小明";
public void Kill()
{
var knife = new Knife();
knife.Kill(name);
}
}
}
然后有一个knife类,具有杀怪的功能
using System;
namespace NoInjection.ConsoleApp
{
public class Knife
{
public void Kill(string name)
{
Console.WriteLine($"{name}用刀杀怪");
}
}
}
最后调用actor实现杀怪
using System;
namespace NoInjection.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var actor = new Actor();
actor.Kill();
Console.ReadKey();
}
}
}
当前的输出就是小明用刀杀怪
依赖注入的方式
构造函数注入
组件的依赖通过构造函数参数进行注入
在Actor中通过构造函数注入knife
namespace ConstructorInjection.ConsoleApp
{
public class Actor
{
private string name = "小明";
private Knife knife;
public Actor(Knife knife)
{
this.knife = knife;
}
public void Kill()
{
knife.Kill(name);
}
}
}
knife类不变
然后主逻辑中创建actor和knife,通过构造函数传入knife
using System;
namespace ConstructorInjection.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var knife = new Knife();
var actor = new Actor(knife);
actor.Kill();
Console.ReadKey();
}
}
}
这个例子我们可以看到,Actor类依赖Knife类,但在Actor不创建Knife,而是通过构造函数传入Knife。
Setter 方法注入(Setter Injection
组件提供 Setter 方法,通过这些方法注入依赖。
Actor中创建setter方法
namespace SetterInjection.ConsoleApp
{
public class Actor
{
private string name = "小明";
private Knife knife;
public Knife Knife
{
set
{
this.knife = value;
}
get
{
return this.knife;
}
}
public void Kill()
{
knife.Kill(name);
}
}
}
knife类同样不变
主逻辑创建actor和knife,并且通过actor的提供的setter方法拿到这把knife
using System;
namespace SetterInjection.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var knife = new Knife();
var actor = new Actor();
actor.Knife = knife;
actor.Kill();
Console.ReadKey();
}
}
}
这个例子我们可以看到,Actor类依赖Knife类,但在Actor不创建Knife,而是通过属性传入Knife。
接口注入(Interface Injection):
组件实现一个接口,并通过接口方法接收依赖。
看不懂