ASP.NET Core依赖注入系统学习教程:ServiceDescriptor(服务注册描述类型) ...

打印 上一主题 下一主题

主题 510|帖子 510|积分 1530

依赖注入容器之所以能够提供应用程序所需的服务对象,是因为服务注册为容器提供了创建服务对象的描述信息,而这个服务注册的描述信息是被封装在一个由ServiceDescriptor类型表示的对象中,该对象主要存储在IServiceCollection类型的集合中,其中每个ServiceDescriptor对象主要描述了:服务的类型、提供服务对象的方式以及服务对象的生命周期模式。
所以可以换句话说,我们进行服务注册实际上就是创建一个ServiceDescriptor类型的对象,并添加到IServiceCollection类型的集合中。基于这种本质也代表了,实际上我们进行服务注册并非要调用注册方法来完成,我们还可以直接创建一个ServiceDescriptor的对象,将其添加到IServiceCollection集合中,用这样的方式同样可以实现服务注册。通过运行下面的代码示例就可以证明这一点。
  1. 1 using Microsoft.Extensions.DependencyInjection;
  2. 2 using System;
  3. 3 using System.Diagnostics;
  4. 4
  5. 5 namespace ConsoleApp1
  6. 6 {
  7. 7     public interface IFooBar { void SayHi(); }
  8. 8     public class FooBar : IFooBar
  9. 9     {
  10. 10         public void SayHi() { Console.WriteLine("你好"); }
  11. 11     }
  12. 12
  13. 13     internal class Program
  14. 14     {
  15. 15         static void Main(string[] args)
  16. 16         {
  17. 17             //创建服务注册信息集合
  18. 18             var collection = new ServiceCollection();
  19. 19
  20. 20             //创建服务注册信息对象,并添加到集合
  21. 21             ServiceDescriptor descriptor = new ServiceDescriptor(typeof(IFooBar), typeof(FooBar), ServiceLifetime.Singleton);
  22. 22             collection.Insert(collection.Count, descriptor);
  23. 23
  24. 24             //构建容器对象
  25. 25             var  provider= collection.BuildServiceProvider();
  26. 26
  27. 27             //获取对象并调用方法
  28. 28             var fooBar =provider.GetService<IFooBar>();
  29. 29             fooBar.SayHi();
  30. 30         } // END Main()
  31. 31
  32. 32     }
  33. 33 }
复制代码
上面的示例中创建ServiceDescriptor对象其实就是通过构造函数传入了几个关键的属性,下面通过代码的形式罗列出ServiceDescriptor类型中的几个关键属性,其中对属性的描述体现在注释上:
  1. 1  public class ServiceDescriptor
  2. 2     {
  3. 3         /// <summary>
  4. 4         /// 服务的生命周期模式
  5. 5         /// </summary>
  6. 6         public ServiceLifetime Lifetime { get; }
  7. 7
  8. 8         /// <summary>
  9. 9         /// 服务的类型,通常会指定一个接口或者基类
  10. 10         /// </summary>
  11. 11         public Type ServiceType { get; }
  12. 12
  13. 13         /// <summary>
  14. 14         /// 服务的实现
  15. 15         /// </summary>
  16. 16         public Type ImplementationType { get; }
  17. 17
  18. 18         /// <summary>
  19. 19         /// 服务实例,直接提供一个实例对象,容器提供时就无需创建
  20. 20         /// </summary>
  21. 21         public object ImplementationInstance { get; }
  22. 22
  23. 23         /// <summary>
  24. 24         /// 用于创建服务实例的工厂方法
  25. 25         /// </summary>
  26. 26         public Func<IServiceProvider, object> ImplementationFactory { get; }
  27. 27
  28. 28     }
复制代码
在以上的关键属性中除了ServiceType(服务类型)是必须的,其他的几个可以根据不同的创建形式使用的不同构造函数来决定。以下是创建ServiceDescriptor类型对象的3个构造函数:
  1. 1 public ServiceDescriptor(Type serviceType, object instance);
  2. 2 public ServiceDescriptor(Type serviceType, Type implementationType, ServiceLifetime lifetime);
  3. 3 public ServiceDescriptor(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime lifetime)
复制代码
ServiceDescriptor类型中的3个构造函数主要体现出了服务实例的3种提供方式,并且这3种提供方式和我们进行服务注册时主要使用的几种形式相得益彰。下面我对这3种服务实例的提供方式进行概况说明:

  • 根据指定的服务类型,直接使用一个现成的对象进行提供;
  • 根据指定的服务类型,使用对应的实现类型结合指定的生命周期模式进行提供;
  • 根据指定的服务类型,使用一个委托对象作为工厂方法,结合指定的生命周期模式进行提供;
第一种方式而言并没有指定生命周期模式,是因为它默认采用了Singleton的模式,所以无需指定生命周期。
除了上面介绍的3个构造函数来创建ServiceDescriptor对象,在ServiceDescriptor类型中还提供了一些列的静态方法用来创建对象。如果想要更加详细的了解ServiceDescriptor类型其中的每一项,可以访问官方文档进行查阅:https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.extensions.dependencyinjection.servicedescriptor?view=dotnet-plat-ext-6.0

总结

服务注册的本质,实际上就是将创建服务对象所使用到的关键信息:服务类型、服务实现类型、提供方式、生命周期,封装到ServiceDescriptor类型的对象中,并添加到IServiceCollection集合,以便作为容器为应用程序提供服务对象的根据。

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

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

祗疼妳一个

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

标签云

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