一、什么是依赖注入(Dependency Injection,DI)
什么是依赖?当一个类需要另一个类协作来完成工作的时候就产生了依赖。
假设,我们有一个关于电影的项目,里面有个控制器(MovieController),有一个Service(MovieService)来做各种具体的实现,比如获取电影名称。
现在我们控制器里面有一个方法要调用Service里面的一个方法(GetMoviceName)来获取电影名称
我们使用传统的new方式来实现,那么Controller 对 Service 就是有依赖关系,假如我们要换一个Service,比如从Ado.Net 换成 Drapper ,那么所有有这个new的地方,都需要改动,依赖性太大。
而我们根据设计原则:依赖于抽象,而不是具体的实现。所以我们需要让调用方来传给你,而不是你去创建它。这就叫注入。
二、依赖注入的三种方法
1、构造函数注入
2、方法注入
3、属性注入
三、在 ASP.NET core中使用依赖注入
看完具体的名词分析后,我们思考一个问题,为什么需要依赖注入?怎么去实现依赖注入呢?还是上面的电影项目,我们通过一段代码示例来说明。
1、传统的实现方式
1 public class MovieService 2 { 3 public string GetMovieName() 4 { 5 return "My Movie Name"; 6 } 7 }
在传统方式下,我们会在Controller里面 new 一个 Service 对象,然后调用方法,如下代码
1 public class MovieController : ControllerBase 2 { 3 MovieService movie = new MovieService(); 4 5 [HttpGet, Route("Movie/GetMovieName")] 6 public string GetMovieName() 7 { 8 return movie.GetMovieName(); 9 } 10 11 }
这样做有个问题,假设我们现在的方案都是用Ado.Net 来做的,现在想改成Drapper,那这样我们新写了一个 Service(MoviceService_UseDrapper),然后我们有N个Controller,里面有好多个地方都用到了 New MovieService(),那就必须要每个地方都要去替换成 New MoviceService_UseDrapper ,数量多且容易出错,那怎么实现呢?这就有了依赖注入的方式。
2、依赖注入方式
还是回到上面的环境代码,我们来做一个修改调整。
第一步我们单独一个接口类(IMoviceService)出来
1 public interface IMoviceService 2 { 3 public string GetMovieName(); 4 }
第二步我们调整我们的MoviceService,从 IMoviceService 继承
1 public class MovieService : IMoviceService 2 { 3 public string GetMovieName() 4 { 5 return "My Movie Name"; 6 } 7 }
第三步我们在 Startup.cs 注册一下
1 public void ConfigureServices(IServiceCollection services) 2 { 3 //注意这里,做个映射 4 services.AddSingleton<IMoviceService,MovieService>(); 5 6 services.AddControllers(); 7 }
第四步Controller代码做个调整,这里我们使用构造函数的方式来实现示例
1 public class MovieController : ControllerBase 2 { 3 //传统方式 4 //MovieService movie = new MovieService(); 5 6 //依赖注入方式 7 IMoviceService movie; 8 public MovieController(IMoviceService moviceService) 9 { 10 movie = moviceService; 11 } 12 13 14 [HttpGet, Route("Movie/GetMovieName")] 15 public string GetMovieName() 16 { 17 return movie.GetMovieName(); 18 } 19 20 }
这样我们就实现了使用依赖注入方式来实现了。
那回到之前的问题,如果我们现在改用 Drapper 了,怎么办呢?
很简单,我们只要按相同方法名实现(MoviceService_UseDrapper)
1 public class MoviceService_UseDrapper: IMoviceService 2 { 3 public string GetMovieName() 4 { 5 return "My Movie Name_Use Drapper"; 6 } 7 }
然后调整Startup.cs 里面的映射关系,就可以了,只需要改一个地方。
1 public void ConfigureServices(IServiceCollection services) 2 { 3 //注意这里,做个映射 4 //services.AddSingleton<IMoviceService,MovieService>(); 5 services.AddSingleton<IMoviceService, MoviceService_UseDrapper>(); //只需要在Startup.cs 调整,整个项目代码就完成修改了 6 7 services.AddControllers(); 8 }
依赖注入解决了一个依赖的关系,也就是解决了 new 的问题,让代码更加清晰,同时更利于后续的更新维护拓展。