IoC:控制反转。在一个有层级的结构中,上层依赖下层,下层的改变会影响上层。控制反转就是将自上而下的依赖链部分反转。由A->B,转变为A->Interface<-B。从中间抽象出一层来,上下2层都依赖他。只要中间这一层不变,则2端可以自由发挥。
DI:依赖注入。虽然自己依赖某个类的运行,但是自己不主动去生成某个实例,而是由调用者去生成(将依赖由自己生成变成外部注入)。自己只需要调用实例的方法即可。
评价:A中过于依赖B,B严重影响A的行为
评价:比原来好,调用时由调用者决定B的实例的生成,A中只负责使用。但是仍然有缺点,不灵活,对B接口的改变的应对方法很笨重。
如果我们想要调用这个A.FunA(),那么一般我们的调用步骤是实例化一个实现Interface接口的类,然后传进去,如下:
A a = new A(); a.FunA(new B());也就是我们人为的将实例B传入Interface接口。我们也可以让程序来帮我们做到这一点。
容器的作用就是一张映射表,将一个接口和一个实现该接口的实体类绑定。没每当我们调用该接口时,则自动的创建该接口映射的实体并返回。
在.Net Core中,该容器本身由.Net来帮我们创建及维护,而我们只需要向其中添加映射关系即可。
在.Net Core使用依赖注入步骤:
1.建立容器
2.向其中添加映射关系
3.获取依赖注入服务提供商
4.在服务提供商中确定一种映射关系
5.使用
使用示例:
//1.建立容器 var serviceCollection = new ServiceCollection() //2.添加映射关系 .AddTransient<Interface, B>(); //3.获取依赖注入服务提供商 var provider = serviceCollection.BuildServiceProvider(); //4.在服务提供商中确定一种映射关系 var b = provider.GetService<Interface>(); //5.直接使用 b.Fun(); //5.当做参数使用 A a = new A(); a.FunA(b);在第二步中的AddTransient表示每一次请求Interface,都会生成一个B实例,这是一种映射关系。
还有其他2中映射关系:AddScope和AddSingleton。
AddScope:在一种请求范围内(scope)只会创建一个实例,哪怕多次创建这个接口。一般用于Asp.Net Core,一个Http请求算是一个Scope
AddSingleton:从项目启动后,之后只创建一次,就和单例模式一样。
var serviceCollection = new ServiceCollection() //2.添加映射关系 .AddTransient<Interface, B>() .AddScoped<Interface, C>() .AddSingleton<Interface, D>();将一个接口映射为3个实体类,以最后一个为准
Transient,Scope,Singleton需要根据实际需求去选择。
在Startup.ConfigureServices已经定义了IServiceCollection接口。我们直接向这个接口中添加映射关系即可。
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddTransient<Interface, B>() .AddScoped<Interface, C>() .AddScoped<Interface, D>(); }在Controller中使用
public class ValuesController : ControllerBase { Interface _b public ValuesController(Interface B) { _b = B; } // GET api/values [HttpGet] public ActionResult<IEnumerable<string>> Get() { _b.Fun(); return new string[] { "value1", "value2" }; } }