ASP.NET Core 服务

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

  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是相同的,说明它在同一请求范围内只创建了一个实例;而暂时服务不管什么范围内每次都会创建;单例始终不变,说明在整个应用程序中只创建了一个实例。

posted @ 2021-10-13 14:33  一纸年华  阅读(555)  评论(0编辑  收藏  举报