.Net Core 依赖注入

打印 上一主题 下一主题

主题 517|帖子 517|积分 1551

依赖注入

控制反转(inversion of control,IOC)是设计模式中非常重要的思想,而依赖注入(dependency injection,DI)是控制反转思想的一种重要的实现方式。依赖注入简化了模块的组装过程,减小了模块之间的耦合度,因此.NET Core中大量应用了依赖注入的开发模式
控制反转

控制反转的目的是将“创建和组装对象”操作的控制权从业务逻辑转移到框架中。当我们需要某个类型的对象时,由框架来提供这个对象,我们不需要关注此对象的创建过程
服务定位器

假设框架中有个ServiceLocator的类,通过调用GetService()就能获取我们想要的对象。至于对象创建过程我们则不需要关心
  1. IDbConnection conn = ServiceLocator.GetService<IDbConnection>();
复制代码
依赖注入
  1. public class Demo
  2. {
  3.     IDbConnection conn;
  4.     public Demo(IDbConnection conn)
  5.     {
  6.         this.conn = conn;
  7.     }
  8. }
复制代码
系统在创建Demo类时,自动为conn 赋一个合适的对象。这种框架自动创建对象的动作就叫做注入
.NET Core 依赖注入的基本使用

.NET Core中内置了控制反转机制,支持依赖注入和服务定位器两种方式。由于依赖注入是推荐的方式,因此微软将内置的控制反转组件命名为DependencyInjection
生命周期

依赖注入框架中注册的服务有一个重要的概念叫做“生命周期”,一共有三种

  • 瞬态(transient)每次被请求的时候都会创建一个新对象
  • 范围(scoped)在给定的范围内,服务每次被请求都会返回同一个对象
  • 单例(singleton)全局共享同一个服务对象
开始使用

安装依赖包
  1. Microsoft.Extensions.DependencyInjection
复制代码
创建接口和实现类
  1. public interface ITestService
  2. {
  3.     public void Run();
  4. }
复制代码
  1. public class TestServiceImpl : ITestService
  2. {
  3.     public void Run()
  4.     {
  5.         Console.WriteLine("我是测试实现类");
  6.     }
  7. }
复制代码
注册服务和获取服务
  1. ServiceCollection services = new ServiceCollection();
  2. services.AddScoped<ITestService, TestServiceImpl>(); //true,因为在同一范围内获取对象所以为true
  3. //services.AddSingleton<ITestService, TestServiceImpl>(); 单例,全局共享一个对象,所以返回true
  4. //services.AddTransient<ITestService, TestServiceImpl>(); 瞬态每次获取都会创建一个新的对象,返回false
  5. using (ServiceProvider sp = services.BuildServiceProvider())
  6. {
  7.     ITestService service1 = sp.GetRequiredService<ITestService>();
  8.     ITestService service2 = sp.GetRequiredService<ITestService>();
  9.     Console.WriteLine(service1 == service2); //true,因为在同一范围内获取对象所以为true
  10.     Console.Read();
  11. }
复制代码
上面通过GetRequiredService方法来获取ITestServcie对象,很显然这种属于服务定位器方式
通过构造函数注入服务

增加服务类
  1. public interface IPayService
  2. {
  3.     public void Pay();
  4. }
复制代码
  1. public class PayServiceImpl : IPayService
  2. {
  3.     public void Pay()
  4.     {
  5.         Console.WriteLine("支付了10元");
  6.     }
  7. }
复制代码
改写TestServiceImpl类
  1. public class TestServiceImpl : ITestService
  2. {
  3.     public IPayService PayService;
  4.     public TestServiceImpl(IPayService PayService)
  5.     {
  6.         this.PayService = PayService;
  7.     }
  8.     public void Run()
  9.     {
  10.         PayService.Pay();
  11.     }
  12. }
复制代码
注册服务和运行
  1. ServiceCollection services = new ServiceCollection();
  2. services.AddScoped<ITestService, TestServiceImpl>();
  3. services.AddScoped<IPayService, PayServiceImpl>();
  4. using (ServiceProvider sp = services.BuildServiceProvider())
  5. {
  6.     ITestService service = sp.GetRequiredService<ITestService>();
  7.     service.Run();
  8. }
复制代码
输出结果:支付了10元
不要在长生命周期的对象中引用比它短的生命周期的对象。比如不能在单例服务中引用范围服务,否则可能会导致被引用的对象已经释放或者导致内存泄漏

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

南飓风

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表