草庐IT

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

坚持 2023-03-28 原文

依赖注入容器之所以能够提供应用程序所需的服务对象,是因为服务注册为容器提供了创建服务对象的描述信息,而这个服务注册的描述信息是被封装在一个由ServiceDescriptor类型表示的对象中,该对象主要存储在IServiceCollection类型的集合中,其中每个ServiceDescriptor对象主要描述了:服务的类型、提供服务对象的方式以及服务对象的生命周期模式。

所以可以换句话说,我们进行服务注册实际上就是创建一个ServiceDescriptor类型的对象,并添加到IServiceCollection类型的集合中。基于这种本质也代表了,实际上我们进行服务注册并非要调用注册方法来完成,我们还可以直接创建一个ServiceDescriptor的对象,将其添加到IServiceCollection集合中,用这样的方式同样可以实现服务注册。通过运行下面的代码示例就可以证明这一点。

 1 using Microsoft.Extensions.DependencyInjection;
 2 using System;
 3 using System.Diagnostics;
 4 
 5 namespace ConsoleApp1
 6 { 
 7     public interface IFooBar { void SayHi(); }
 8     public class FooBar : IFooBar
 9     {
10         public void SayHi() { Console.WriteLine("你好"); }
11     }
12 
13     internal class Program
14     {
15         static void Main(string[] args)
16         {
17             //创建服务注册信息集合
18             var collection = new ServiceCollection();
19 
20             //创建服务注册信息对象,并添加到集合
21             ServiceDescriptor descriptor = new ServiceDescriptor(typeof(IFooBar), typeof(FooBar), ServiceLifetime.Singleton);
22             collection.Insert(collection.Count, descriptor);
23 
24             //构建容器对象
25             var  provider= collection.BuildServiceProvider();
26 
27             //获取对象并调用方法
28             var fooBar =provider.GetService<IFooBar>();
29             fooBar.SayHi();
30         } // END Main()
31 
32     }
33 }

上面的示例中创建ServiceDescriptor对象其实就是通过构造函数传入了几个关键的属性,下面通过代码的形式罗列出ServiceDescriptor类型中的几个关键属性,其中对属性的描述体现在注释上:

 1  public class ServiceDescriptor
 2     {
 3         /// <summary>
 4         /// 服务的生命周期模式
 5         /// </summary>
 6         public ServiceLifetime Lifetime { get; }
 7 
 8         /// <summary>
 9         /// 服务的类型,通常会指定一个接口或者基类
10         /// </summary>
11         public Type ServiceType { get; }
12 
13         /// <summary>
14         /// 服务的实现
15         /// </summary>
16         public Type ImplementationType { get; }
17 
18         /// <summary>
19         /// 服务实例,直接提供一个实例对象,容器提供时就无需创建
20         /// </summary>
21         public object ImplementationInstance { get; }
22 
23         /// <summary>
24         /// 用于创建服务实例的工厂方法
25         /// </summary>
26         public Func<IServiceProvider, object> ImplementationFactory { get; }
27 
28     }

在以上的关键属性中除了ServiceType(服务类型)是必须的,其他的几个可以根据不同的创建形式使用的不同构造函数来决定。以下是创建ServiceDescriptor类型对象的3个构造函数:

1 public ServiceDescriptor(Type serviceType, object instance);
2 public ServiceDescriptor(Type serviceType, Type implementationType, ServiceLifetime lifetime);
3 public ServiceDescriptor(Type serviceType, Func<IServiceProvider, object> factory, ServiceLifetime lifetime)

ServiceDescriptor类型中的3个构造函数主要体现出了服务实例的3种提供方式,并且这3种提供方式和我们进行服务注册时主要使用的几种形式相得益彰。下面我对这3种服务实例的提供方式进行概况说明:

  1. 根据指定的服务类型,直接使用一个现成的对象进行提供;
  2. 根据指定的服务类型,使用对应的实现类型结合指定的生命周期模式进行提供;
  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集合,以便作为容器为应用程序提供服务对象的根据。

有关ASP.NET Core依赖注入系统学习教程:ServiceDescriptor(服务注册描述类型)的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  4. ruby-on-rails - 在 ruby​​ .gemspec 文件中,如何指定依赖项的多个版本? - 2

    我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这

  5. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  6. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  7. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  8. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  9. postman接口测试工具-基础使用教程 - 2

    1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,

  10. LC滤波器设计学习笔记(一)滤波电路入门 - 2

    目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称

随机推荐