控制反转(inversion of control,IOC)是设计模式中非常重要的思想,而依赖注入(dependency injection,DI)是控制反转思想的一种重要的实现方式。依赖注入简化了模块的组装过程,减小了模块之间的耦合度,因此.NET Core中大量应用了依赖注入的开发模式
公司主营业务:网站制作、做网站、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出横县免费做网站回馈大家。
控制反转的目的是将“创建和组装对象”操作的控制权从业务逻辑转移到框架中。当我们需要某个类型的对象时,由框架来提供这个对象,我们不需要关注此对象的创建过程
假设框架中有个ServiceLocator的类,通过调用GetService()
就能获取我们想要的对象。至于对象创建过程我们则不需要关心
IDbConnection conn = ServiceLocator.GetService();
public class Demo
{
IDbConnection conn;
public Demo(IDbConnection conn)
{
this.conn = conn;
}
}
系统在创建Demo
类时,自动为conn
赋一个合适的对象。这种框架自动创建对象的动作就叫做注入
.NET Core中内置了控制反转机制,支持依赖注入和服务定位器两种方式。由于依赖注入是推荐的方式,因此微软将内置的控制反转组件命名为DependencyInjection
依赖注入框架中注册的服务有一个重要的概念叫做“生命周期”,一共有三种
安装依赖包
Microsoft.Extensions.DependencyInjection
创建接口和实现类
public interface ITestService
{
public void Run();
}
public class TestServiceImpl : ITestService
{
public void Run()
{
Console.WriteLine("我是测试实现类");
}
}
注册服务和获取服务
ServiceCollection services = new ServiceCollection();
services.AddScoped(); //true,因为在同一范围内获取对象所以为true
//services.AddSingleton(); 单例,全局共享一个对象,所以返回true
//services.AddTransient(); 瞬态每次获取都会创建一个新的对象,返回false
using (ServiceProvider sp = services.BuildServiceProvider())
{
ITestService service1 = sp.GetRequiredService();
ITestService service2 = sp.GetRequiredService();
Console.WriteLine(service1 == service2); //true,因为在同一范围内获取对象所以为true
Console.Read();
}
上面通过GetRequiredService方法来获取ITestServcie对象,很显然这种属于服务定位器方式
增加服务类
public interface IPayService
{
public void Pay();
}
public class PayServiceImpl : IPayService
{
public void Pay()
{
Console.WriteLine("支付了10元");
}
}
改写TestServiceImpl类
public class TestServiceImpl : ITestService
{
public IPayService PayService;
public TestServiceImpl(IPayService PayService)
{
this.PayService = PayService;
}
public void Run()
{
PayService.Pay();
}
}
注册服务和运行
ServiceCollection services = new ServiceCollection();
services.AddScoped();
services.AddScoped();
using (ServiceProvider sp = services.BuildServiceProvider())
{
ITestService service = sp.GetRequiredService();
service.Run();
}
输出结果:支付了10元
不要在长生命周期的对象中引用比它短的生命周期的对象。比如不能在单例服务中引用范围服务,否则可能会导致被引用的对象已经释放或者导致内存泄漏