依赖注入由依赖注入框架在运行时完成。 .NET has one built in already as an extension.
从超类继承或实现接口根本不涉及依赖注入,这是在语言本身中静态完成的。
当一个类使用依赖注入时,它要么在构造函数中将其依赖作为参数,这是执行此操作的常用方法,要么通过让其属性具有直接注入的值,这需要一个 [attribute ] 标记依赖注入的属性。
经典就是一个例子:
public PeopleController(ILogger logger) {...}
如您所见,PeopleController 类的此构造函数采用ILogger 类型的参数,这是一个接口。依赖注入框架注意到了这一点,当实例化这个控制器时,它会注入一个实现ILogger接口的类的实例。
通常你尝试通过接口注入,因为这会解耦你的代码并遵循dependency inversion,这就是依赖注入的真正意义所在。在谈论依赖注入时,通常称为inversion of control。
另一个例子,假设你有这个PeopleController,它想要注入一个IPeopleService:
public class PeopleController
{
private readonly IPeopleService _peopleService;
public PeopleController(IPeopleService peopleService)
{
_peopleService = peopleService;
}
public void MethodThatUsesPeopleService() {
_peopleService.makePeopleHappy();
}
}
IPeopleService 接口:
public interface IPeopleService
{
void makePeopleHappy();
}
现在,您有一个想要注入服务的控制器,因此您需要告诉依赖注入框架将哪个类与接口关联。
你可以为同一个接口创建两个不同的实现:
public class GoodPeopleService : IPeopleService
{
public void makePeopleHappy()
{
Console.WriteLine("People are now happy!");
}
}
public class BadPeopleService : IPeopleService
{
public void makePeopleHappy()
{
Console.WriteLine("People are NOT happy now HAHA!");
}
}
根据您告诉依赖注入框架与IPeopleService 接口关联的其中哪一个,您将从PeopleController 中获得不同的行为。
关于如何将类注册到接口的详细信息,请查看Microsoft's Documentation。这是它的外观的 sn-p:
services.AddScoped<IPeopleService, GoodPeopleService>();
请参阅service lifetimes,了解有关注册服务时要调用的扩展方法的信息。
附带说明:依赖注入是在运行时完成的,这意味着在编译时不存在所请求接口或类的实例的静态保证。尽管有了 C# 的更新功能,但有一些依赖注入框架旨在解决这个问题。 (见Jab和StrongInject)