文章目录
一、什么是控制反转(Inversion of Control ,简称IOC)
控制反转,是面向对象编程中的一种设计原则,可以减少代码之间的耦合度,其中最常见的方式叫做依赖注入(Dependency Injection , 简称DI)
1.IOC代码层面解释:
调用者不在创建(不自己new)被调用者的实例,而是交给容器去创建,这个就是控制反转
2.DI代码层面解释:
容器创建好实例在注入调用者的过程,就是依赖注入(比如:属性注入、构造函数注入等)。
二、为什么要使用IOC
我们常用的设计模式为接口驱动设计,接口驱动设计有很多好处,提供不同灵活的子类实现,
但是接口一定是需要实现的,也就是初始化实例一定会执行,
所以就会出现一些问题:多个子类按照一般的方法实现同一个接口,即会出现耦合
1.测试代码(耦合代码)
第一步: 新建一个
.net core API程序ioc_demo
第二步:创建一个接口:
ITestService.cs
using System;
namespace ioc_demo.@interface
{
public interface ITestService
{
//声明一个属性一个方法
int Count { get; }
void Add();
}
}
第三步:新建一个实现接口的类:
TestServiceImpl.cs
using System;
using ioc_demo.@interface;
namespace ioc_demo.lmpl
{
public class TestServiceImpl : ITestService
{
private int _count;
public TestServiceImpl()
{
_count = 0;
Console.WriteLine("服务创建");
}
public int Count => _count;
public void Add()
{
_count++;
}
}
}
第四步:创建一个新的control:
TestController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ioc_demo.@interface;
using ioc_demo.lmpl;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace ioc_demo.Controllers
{
[Route("api/[controller]")]
public class TestController : Controller
{
// GET: api/values
[HttpGet]
public Tuple<int,int> Get()
{
ITestService testService = new TestServiceImpl(); //接口实现类,程序耦合
int first = testService.Count;
testService.Add();
int second = testService.Count;
Console.WriteLine(first);
Console.WriteLine(second);
return new Tuple<int, int>(first, second);
}
}
}
三、IOC如何降低耦合
1.情景再现:
两个类互相调用,一般情况ClassA中使用带了ClassB中的对象或者属性方法,那么就需要在ClassA中显式的new一个ClassB
2.IOC实现原理
采用依赖注入技术之后,ClassA的代码只需要定义一个私有的ClassB对象,不要用通过实例化new出来这个ClassB,而是通过相关的容器控制程序将ClassB对象在容器中new出来并注入到ClassA类里的引用中。 具体的获取方法、对象获取时的状态则需要配置来制定
四、 IOC模式中的容器
1.容器的解释
IOC模式,系统通过引入实现了IOC模式的IOC容器,即可由IOC容器来管理对象的生命周期、依赖关系、从而使得应用程序的配置和依赖性规范与实际的应用程序代码分离。
最大的好处:修改程序组件间的配置,而不需要重新修改编译具体的代码
2. .net core 自带容器的使用
- AddTransient:瞬时的,每次访问构造一个
在
Startup.cs
类ConfigureServices
中添加以下代码
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddTransient<ITestService, TestServiceImpl>();//注入服务 瞬时模式
}
将
TestController.cs
中代码替换为下列代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ioc_demo.@interface;
using ioc_demo.lmpl;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace ioc_demo.Controllers
{
[Route("api/[controller]")]
public class TestController : Controller
{
private ITestService _service;
public TestController(ITestService testService)
{
_service = testService;
}
// GET: api/values
[HttpGet]
public Tuple<int,int> Get()
{
//ITestService testService = new TestServiceImpl(); //接口实现类,程序耦合
int first = _service.Count;
_service.Add();
int second = _service.Count;
Console.WriteLine(first);
Console.WriteLine(second);
return new Tuple<int, int>(first, second);
}
}
}
总结:每次访问接口,
TestServiceImpl构造函数
中都会执行Console.WriteLine("服务创建");
符合瞬时创建构造函数的特性
- AddSingleton: 单例,全局只有一个
在
Startup.cs
类ConfigureServices
中替换以下代码
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSingleton<ITestService, TestServiceImpl>(); //注入服务 单例模式
}
总结:每次访问接口,
TestServiceImpl构造函数
中都只会执行Console.WriteLine("服务创建");
一次, 符合单例模式的特性
- AddScoped : 在同作用域、服务每次请求只创建一个
在
Startup.cs
类ConfigureServices
中添加以下代码
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<ITestService, TestServiceImpl>();//注入服务 作用域模式
}
将
TestController.cs
中代码替换为下列代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using ioc_demo.@interface;
using ioc_demo.lmpl;
using Microsoft.AspNetCore.Mvc;
// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860
namespace ioc_demo.Controllers
{
[Route("api/[controller]")]
public class TestController : Controller
{
private ITestService _service;
public TestController(ITestService testService)
{
_service = testService;
}
// GET: api/values
[HttpGet]
public Tuple<int,int> Get([FromServices]ITestService service)
{
//ITestService testService = new TestServiceImpl(); //接口实现类,程序耦合
service.Add();
int first = _service.Count;
_service.Add();
int second = _service.Count;
Console.WriteLine(first);
Console.WriteLine(second);
//如果返回1,2 说明service 与 _service是同一个对象
return new Tuple<int, int>(first, second);
}
}
}
总结:在此作用域使用服务,只会创建一个;