目录



枚举出程序中已添加的服务

  Asp.Net Core 项目中的“服务”,指的是用于扩展应用程序功能的一系列类型。

  在程序初始化期间,会把需要的服务类型实例添加到ServiceCollection集合中,这些服务实例将通过依赖注入提供给其他代码使用。

  下面遍历一下已添加的服务:

    public static void Main(string[] args)
{
var host = new WebHostBuilder()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseKestrel()
.UseStartup<Startup>()
.Build();
host.Run();
}
    public void ConfigureServices(IServiceCollection services)
{
foreach (var sv in services)
{
string msg = $"服务类型:{sv.ServiceType?.Name ?? "<>"}";
msg += $",实现类型:{sv.ImplementationType?.Name ?? "<>"}";
Console.WriteLine(msg);
}
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.Run(async (context) =>
{
await context.Response.WriteAsync("Hello World!");
});
}


结果:

    服务类型:IOptionsSnapshot`1,实现类型:OptionsManager`1
服务类型:IOptionsMonitor`1,实现类型:OptionsMonitor`1
服务类型:IOptionsFactory`1,实现类型:OptionsFactory`1
服务类型:IOptionsMonitorCache`1,实现类型:OptionsCache`1
服务类型:ILoggerFactory,实现类型:LoggerFactory
服务类型:ILogger`1,实现类型:Logger`1
服务类型:IConfigureOptions`1,实现类型:<无>
服务类型:IStartupFilter,实现类型:AutoRequestServicesStartupFilter
服务类型:IServiceProviderFactory`1,实现类型:DefaultServiceProviderFactory
服务类型:ObjectPoolProvider,实现类型:DefaultObjectPoolProvider
服务类型:ITransportFactory,实现类型:SocketTransportFactory
服务类型:IConfigureOptions`1,实现类型:KestrelServerOptionsSetup
服务类型:IServer,实现类型:KestrelServer
服务类型:IStartup,实现类型:<无>
服务类型:DiagnosticListener,实现类型:<无>
服务类型:DiagnosticSource,实现类型:<无>
服务类型:IApplicationLifetime,实现类型:ApplicationLifetime
服务类型:IApplicationLifetime,实现类型:<无>
服务类型:HostedServiceExecutor,实现类型:HostedServiceExecutor


服务类型

  编写服务类型有三种方案:

  (1)接口实现形式;

  (2)抽象类实现形式;

  (3)直接定义类形式;

    public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IService1, MyService1>(); // 接口实现
services.AddSingleton<ServiceBase, MyService2>(); // 抽象类实现
services.AddSingleton<MyService3>(); // 直接定义类
}


服务生命周期

  服务类型添加到​​ServiceCollection​​容器后,其生命周期将由框架自动管理。

  容器中存在三种服务生命周期:

  (1)暂时服务:通过调用​​AddTransient​​方法添加。服务生命周期最短,每次被请求都会实例化一次,属于轻量级服务。就算在同一请求中多次访问,暂时服务每次都会实例化。

  (2)作用域服务:通过调用​​AddScoped​​方法添加。这个范围是单个请求中,不管被请求多少次,都只实例化一次。

  (3)单例服务:通过调用​​AddSingleton​​方法添加。它在整个应用程序运行期间不管多少次请求只创建一个实例。

  • 实例:

  Asp.Net Core Web应用程序项目中,先声明一个ServiceBase类,作为三个服务的共同基类,主要作用是产生新的Guid。

    public class ServiceBase
{
public Guid ID { get; }

protected ServiceBase()
{
ID = Guid.NewGuid();
}
}


  ServiceBase派生三个类,代表三个服务。

    public sealed class ServiceA : ServiceBase { }
public sealed class ServiceB : ServiceBase { }
public sealed class ServiceC : ServiceBase { }


  再定义一个类,用来在构造函数中接收来自前三个服务的注入。

    public class ServiceDependencyAll
{
public ServiceDependencyAll(ServiceA sva, ServiceB svb, ServiceC svc)
{
Service_A = sva;
Service_B = svb;
Service_C = svc;
}

public ServiceBase Service_A { get; }
public ServiceBase Service_B { get; }
public ServiceBase Service_C { get; }
}


  定义Demo控制器,在其构造函数中注入四个服务。Check方法作为MVC中的Action。

    public class DemoController : Controller
{
private readonly ServiceA _serviceA = null;
private readonly ServiceB _serviceB = null;
private readonly ServiceC _serviceC = null;
private readonly ServiceDependencyAll _serviceDep = null;

public DemoController(ServiceA a, ServiceB b, ServiceC c,ServiceDependencyAll d)
{
_serviceA = a;
_serviceB = b;
_serviceC = c;
_serviceDep = d;
}

public IActionResult Check()
{
List<string> strLines = new List<string>();
strLines.Add($"暂时服务:{_serviceA.ID}");
strLines.Add($"作用域服务:{_serviceB.ID}");
strLines.Add($"单一实例服务:{_serviceC.ID}");
strLines.Add(string.Empty);
strLines.Add("存在依赖关系的服务:");
strLines.Add($"暂时服务:{_serviceDep.Service_A.ID}");
strLines.Add($"作用域服务:{_serviceDep.Service_B.ID}");
strLines.Add($"单一实例服务:{_serviceDep.Service_C.ID}");
return View("~/DemoView.cshtml", strLines);
}
}


  DemoView.cshtml页面。

@model IList<string>

<html>
<body>
<div>
@{
foreach (string line in Model)
{
@line <br/>
}
}
</div>
</body>
</html>


  把前面定义的四个服务都添加到服务容器中。

    public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();

services.AddTransient<ServiceA>();
services.AddScoped<ServiceB>();
services.AddSingleton<ServiceC>();

services.AddTransient<ServiceDependencyAll>();
}


  运行程序,在浏览器(我的是 ​​http://localhost:54450/Demo/Check​​ )中访问。进行三次请求,观察生成的Guid。

  第一次:

    暂时服务:baeee348-a41e-43fa-bd9f-cb8b97813e45
作用域服务:acc22a18-eef9-45c5-a216-3c0adbe4d453
单一实例服务:79fd5729-b651-4f4d-9a40-35ed42a393e7

存在依赖关系的服务:
暂时服务:d68e412a-85b2-4e1c-9ab5-3fea97a44a23
作用域服务:acc22a18-eef9-45c5-a216-3c0adbe4d453
单一实例服务:79fd5729-b651-4f4d-9a40-35ed42a393e7


  第二次:

    暂时服务:b5627905-175f-4691-b691-1afb85a534ff
作用域服务:96cd6e17-dd7b-47e4-a407-25564082e194
单一实例服务:79fd5729-b651-4f4d-9a40-35ed42a393e7

存在依赖关系的服务:
暂时服务:2ea9b719-2e68-4136-972b-a6a3e67729d6
作用域服务:96cd6e17-dd7b-47e4-a407-25564082e194
单一实例服务:79fd5729-b651-4f4d-9a40-35ed42a393e7


  第三次:

    暂时服务:85d4da68-2d52-47db-aca8-01b63f89bb5d
作用域服务:a8ac3436-b53a-46be-b467-ea0474516783
单一实例服务:79fd5729-b651-4f4d-9a40-35ed42a393e7

存在依赖关系的服务:
暂时服务:10783740-2e4e-41ee-91c7-22f75713366e
作用域服务:a8ac3436-b53a-46be-b467-ea0474516783
单一实例服务:79fd5729-b651-4f4d-9a40-35ed42a393e7


  结果可以看出,在同一次请求中,作用域服务被访问了两次,但Guid是相同的,说明它在同一请求范围内只创建了一个实例;而暂时服务不管什么范围内每次都会创建;单例始终不变,说明在整个应用程序中只创建了一个实例。