什么是依赖注⼊
1 定义
依赖注⼊(Dependency Injection),简称DI,类之间的依赖关系由容器来负责。简单来讲a依赖b,但a不创建(或销毁)b,仅使⽤b,b的创建(或销毁)交给容器。
2 例⼦
为了把DI讲清楚,我们需要举⼀个简单例⼦。例⼦⾜够⼩,希望让你能直观的了解DI⽽不会陷⼊真实⽰例的泥潭。
例⼦:⼩明要杀怪,那⼩明拿什么武器杀怪呢?可以⽤⼑、也可以⽤拳头、斧⼦等。
⾸先,我们创建⼀个演员类,名字叫“⼩明”,具有杀怪功能。
namespace NoInjection.ConsoleApp
{
public class Actor
namespace是干嘛的{
private string name = "⼩明";
public void Kill()
{
var knife = new Knife();
knife.Kill(name);
}
}
}
然后,我们再创建⼀个武器-⼑类,具有杀怪功能。
using System;
namespace NoInjection.ConsoleApp
{
public class Knife
{
public void Kill(string name)
{
Console.WriteLine($"{name}⽤⼑杀怪");
}
}
}
最后,我们客户端调⽤演员类,执⾏杀怪功能。
using System;
namespace NoInjection.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var actor = new Actor();
actor.Kill();
Console.ReadKey();
}
}
}
让我们来看看输出结果:
⼩明⽤⼑杀怪
通过这个例⼦我们可以看到,Actor类依赖Knife类,在Actor中创建Knife,执⾏Knife.Kill⽅法。我们可以回顾⼀下DI的定义,a依赖b,但a不创建(或销毁)b,仅使⽤b,显然这个不符合DI做法。
DI下⾯我们详细说说DI的⼏种形式。
3 形式
3.1 构造函数注⼊
⾸先,我们在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类不需要变化。
using System;
namespace ConstructorInjection.ConsoleApp
{
public class Knife
{
public void Kill(string name)
{
Console.WriteLine($"{name}⽤⼑杀怪");
}
}
}
最后,我们客户端来创建Actor和Knife,然后在Actor通过构造函数传⼊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。
3.2 Setter注⼊
⾸先,我们在Actor类创建Knife属性。
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类不需要变化。
using System;
namespace SetterInjection.ConsoleApp
{
public class Knife
{
public void Kill(string name)
{
Console.WriteLine($"{name}⽤⼑杀怪");
}
}
}
最后,我们客户端来创建Actor和Knife,然后在Actor通过属性传⼊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。
3.3 接⼝注⼊
⾸先,我们在Actor类创建Knife属性并继承IActor
namespace InterfaceInjection.ConsoleApp
{
interface IActor
{
Knife Knife { set; get; }
void Kill();
}
}
namespace InterfaceInjection.ConsoleApp
{
public class Actor: IActor
{
private string name = "⼩明";
private Knife knife;
public Knife Knife
{
set
{
this.knife = value;
}
get
{
return this.knife;
}
}
public void Kill()
{
knife.Kill(name);
}
}
}
然后,Knife类不需要变化。
using System;
namespace InterfaceInjection.ConsoleApp
{
public class Knife
{
public void Kill(string name)
{
Console.WriteLine($"{name}⽤⼑杀怪");
}
}
}
最后,我们客户端来创建Actor和Knife,然后在Actor通过属性传⼊Knife。
using System;
namespace InterfaceInjection.ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var knife = new Knife();
IActor actor = new Actor();
actor.Knife = knife;
actor.Kill();
Console.ReadKey();
}
}
}
接⼝注⼊⽅式我理解了也不是很透,感觉跟Setter注⼊没有什么⼤的差别,只是增加了⼀个接⼝定义。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论