借助 .NET提供的服务承载(Hosting)系统,我们可以将一个或者多个长时间运行的后台服务寄宿或者承载我们创建的应用中。任何需要在后台长时间运行的操作都可以定义成标准化的服务并利用该系统来承载,ASP.NET Core应用最终也体现为这样一个承载服务。(本篇提供的实例已经汇总到《ASP.NET Core 6框架揭秘-实例演示版》)

[S1407]利用IHostApplicationLifetime对象关闭应用(源代码

[S1408]与第三方依赖注入框架的整合(源代码

[S1409]利用配置初始化承载环境(源代码

[S1407]利用IHostApplicationLifetime对象关闭应用

我们接下来通过一个简单的实例演示如何利用IHostApplicationLifetime服务来关闭整个承载应用。我们在一个控制台应用程序中定义了如下这个承载服务类型FakeHostedService,并在其构造函数中注入了IHostApplicationLifetime服务。在得到其三个属性返回的CancellationToken对象之后,我们在它们上面分别注册了一个回调在控制台输出相应的文字。

public sealed class FakeHostedService : IHostedService
{
private readonly IHostApplicationLifetime _lifetime;
private IDisposable? _tokenSource; public FakeHostedService(IHostApplicationLifetime lifetime)
{
_lifetime = lifetime;
_lifetime.ApplicationStarted.Register(() => Console.WriteLine("[{0}]Application started", DateTimeOffset.Now));
_lifetime.ApplicationStopping.Register(() => Console.WriteLine("[{0}]Application is stopping.", DateTimeOffset.Now));
_lifetime.ApplicationStopped.Register(() => Console.WriteLine("[{0}]Application stopped.", DateTimeOffset.Now));
} public Task StartAsync(CancellationToken cancellationToken)
{
_tokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token.Register(_lifetime.StopApplication);
return Task.CompletedTask;
} public Task StopAsync(CancellationToken cancellationToken)
{
_tokenSource?.Dispose();
return Task.CompletedTask;
}
}

在实现的StartAsync方法中,我们采用如上的方式在等待5秒之后调用IHostApplicationLifetime对象的StopApplication方法关闭应用程序。FakeHostedService服务最后采用如下所示的方式承载于当前应用程序中。

using App;
Host.CreateDefaultBuilder(args)
.ConfigureServices(svcs => svcs.AddHostedService<FakeHostedService>())
.Build()
.Run();

该程序运行之后在控制台上输出的结果如图1所示,从三条消息输出的时间间隔可以确定当前应用程序正是承载FakeHostedService通过调用IHostApplicationLifetime服务的StopApplication方法关闭的。


图1 调用IHostApplicationLifetime服务关闭应用程序

[S1408]与第三方依赖注入框架的整合

一个Mini版的依赖注入框架》中创建了一个名为Cat的简易版依赖注入框架,并在《与第三方依赖注入框架Cat的整合》中为其创建了一个IServiceProviderFactory<TContainerBuilder>实现类型,具体类型为CatServiceProvider,我们接下来演示一下如何通过注册CatServiceProvider实现与Cat这个第三方依赖注入框架的整合。在创建的演示程序中,我们采用这样的方式定义了三个服务(Foo、Bar和Baz)和对应的接口(IFoo、IBar和IBaz),并在服务类型上标注MapToAttribute特性来定义服务注册信息。

public interface IFoo { }
public interface IBar { }
public interface IBaz { } [MapTo(typeof(IFoo), Lifetime.Root)]
public class Foo : IFoo { } [MapTo(typeof(IBar), Lifetime.Root)]
public class Bar : IBar { } [MapTo(typeof(IBaz), Lifetime.Root)]
public class Baz : IBaz { }

如下所示的FakeHostedService类型表示承载的服务。我们在构造函数中注入了IFoo、IBar和IBaz对象,构造函数提供的调试断言用于验证上述三个服务被成功注入。

public sealed class FakeHostedService: IHostedService
{
public FakeHostedService(IFoo foo, IBar bar, IBaz baz)
{
Debug.Assert(foo != null);
Debug.Assert(bar != null);
Debug.Assert(baz != null);
}
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}

我们在如下的演示程序中创建了一个IHostBuilder对象,通过调用其ConfigureServices方法注册了需要承载的FakeHostedService服务后,我们调用它的UseServiceProviderFactory方法完成了对CatServiceProvider的注册。我们随后调用了CatBuilder的Register方法完成了针对入口程序集的批量服务注册。调用IHostBuilder的Build方法构建出作为宿主的IHost对象并启动它之后,承载的FakeHostedService服务将自动被创建并启动(S1408)。

using App;
using System.Reflection; Host.CreateDefaultBuilder()
.ConfigureServices(svcs => svcs.AddHostedService<FakeHostedService>())
.UseServiceProviderFactory(new CatServiceProviderFactory())
.ConfigureContainer<CatBuilder>(
builder => builder.Register(Assembly.GetEntryAssembly()!))
.Build()
.Run();

[S1409]利用配置初始化承载环境

一个HostBuilderContext上下文由承载针对宿主配置的IConfiguration对象和描述当前承载环境的IHostEnvironment对象组成,后者提供的环境名称、应用名称和内容文件根目录路径可以通过前者来指定,具体的配置项名称定义在如下这个静态类型HostDefaults中。

public static class HostDefaults
{
public static readonly string EnvironmentKey = "environment";
public static readonly string ContentRootKey = "contentRoot";
public static readonly string ApplicationKey = "applicationName";
}

下面我们通过一个简单的实例演示如何利用配置的方式来指定上述三个与承载环境相关的属性。我们定义了如下一个名为FakeHostedService的承载服务,并在构造函数中注入IHostEnvironment对象。FakeHostedService派生于抽象类BackgroundService,我们在在ExecuteAsync方法中将与承载环境相关的环境名称、应用名称和内容文件根目录路径输出到控制台上。

public class FakeHostedService : BackgroundService
{
private readonly IHostEnvironment _environment;
public FakeHostedService(IHostEnvironment environment) => _environment = environment;
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
Console.WriteLine("{0,-15}:{1}", nameof(_environment.EnvironmentName), _environment.EnvironmentName);
Console.WriteLine("{0,-15}:{1}", nameof(_environment.ApplicationName),_environment.ApplicationName);
Console.WriteLine("{0,-15}:{1}", nameof(_environment.ContentRootPath),_environment.ContentRootPath);
return Task.CompletedTask;
}
}

FakeHostedService采用如下形式进行承载。如代码片段所示,为了避免输出日志的“干扰”,我们调用IHostBuilder接口的ConfigureLogging扩展方法将注册的ILoggerProvider对象全部清除。如果调用Host静态类型的CreateDefaultBuilder方法时传入当前的命令行参数,创建的IHostBuilder对象会将其作为配置源,所以我们就能以命令行参数的形式来指定承载上下文的三个属性。

using App;
Host.CreateDefaultBuilder(args)
.ConfigureLogging(logging=>logging.ClearProviders())
.ConfigureServices(svcs => svcs.AddHostedService<FakeHostedService>())
.Build()
.Run();

我们采用命令行的方式启动这个演示程序,并利用传入的命令行参数指定环境名称、应用名称和内容文件根目录路径(确保路径确实存在)。图2所示的输出结果表明,应用程序当前的承载环境与基于宿主的配置是一致的。


图2 利用配置来初始化承载环境

ASP.NET Core 6框架揭秘实例演示[22]:如何承载你的后台服务[补充]的更多相关文章

  1. ASP.NET Core 6框架揭秘实例演示[07]:文件系统

    ASP.NET Core应用具有很多读取文件的场景,如读取配置文件.静态Web资源文件(如CSS.JavaScript和图片文件等).MVC应用的视图文件,以及直接编译到程序集中的内嵌资源文件.这些文 ...

  2. ASP.NET Core 6框架揭秘实例演示[08]:配置的基本编程模式

    .NET的配置支持多样化的数据源,我们可以采用内存的变量.环境变量.命令行参数.以及各种格式的配置文件作为配置的数据来源.在对配置系统进行系统介绍之前,我们通过几个简单的实例演示一下如何将具有不同来源 ...

  3. ASP.NET Core 6框架揭秘实例演示[09]:配置绑定

    我们倾向于将IConfiguration对象转换成一个具体的对象,以面向对象的方式来使用配置,我们将这个转换过程称为配置绑定.除了将配置树叶子节点配置节的绑定为某种标量对象外,我们还可以直接将一个配置 ...

  4. ASP.NET Core 6框架揭秘实例演示[10]:Options基本编程模式

    依赖注入使我们可以将依赖的功能定义成服务,最终以一种松耦合的形式注入消费该功能的组件或者服务中.除了可以采用依赖注入的形式消费承载某种功能的服务,还可以采用相同的方式消费承载配置数据的Options对 ...

  5. ASP.NET Core 6框架揭秘实例演示[11]:诊断跟踪的几种基本编程方式

    在整个软件开发维护生命周期内,最难的不是如何将软件系统开发出来,而是在系统上线之后及时解决遇到的问题.一个好的程序员能够在系统出现问题之后马上定位错误的根源并找到正确的解决方案,一个更好的程序员能够根 ...

  6. ASP.NET Core 6框架揭秘实例演示[12]:诊断跟踪的进阶用法

    一个好的程序员能够在系统出现问题之后马上定位错误的根源并找到正确的解决方案,一个更好的程序员能够根据当前的运行状态预知未来可能发生的问题,并将问题扼杀在摇篮中.诊断跟踪能够帮助我们有效地纠错和排错&l ...

  7. ASP.NET Core 6框架揭秘实例演示[13]:日志的基本编程模式[上篇]

    <诊断跟踪的几种基本编程方式>介绍了四种常用的诊断日志框架.其实除了微软提供的这些日志框架,还有很多第三方日志框架可供我们选择,比如Log4Net.NLog和Serilog 等.虽然这些框 ...

  8. ASP.NET Core 6框架揭秘实例演示[14]:日志的进阶用法

    为了对各种日志框架进行整合,微软创建了一个用来提供统一的日志编程模式的日志框架.<日志的基本编程模式>以实例演示的方式介绍了日志的基本编程模式,现在我们来补充几种"进阶" ...

  9. ASP.NET Core 6框架揭秘实例演示[15]:针对控制台的日志输出

    针对控制台的ILogger实现类型为ConsoleLogger,对应的ILoggerProvider实现类型为ConsoleLoggerProvider,这两个类型都定义在 NuGet包"M ...

随机推荐

  1. .net core部署到ubuntu 上传文件超过30MB

    默认的上传文件不能超过30MB,需要修改几个地方 一.web.config中添加配置 <requestLimits maxAllowedContentLength="214748364 ...

  2. aidl的应用场景

    支付宝 package com.tesy.alipay; import com.test.alipay.Iservice.Stub; import android.app.Service; impor ...

  3. android+json+php+mysql实现用户反馈功能

    相信每个项目都会有用户反馈建议等功能,这个实现的方法很多,下面是我实现的方法,供大家交流.首先看具体界面,三个字段.名字,邮箱为选填,可以为空,建议不能为空.如有需要可以给我留言. 下面贴出布局代码, ...

  4. 编译安装http2.4

    编译安装http2.4 1.安装相关依赖包 [root@centos7 ~]yum -y install gcc make 2.下载http2.4包,并解压 [root@centos7 ~]#tar ...

  5. Redis 在 vivo 推送平台的应用与优化实践

    一.推送平台特点 vivo推送平台是vivo公司向开发者提供的消息推送服务,通过在云端与客户端之间建立一条稳定.可靠的长连接,为开发者提供向客户端应用实时推送消息的服务,支持百亿级的通知/消息推送,秒 ...

  6. unittest基础篇1

    转自http://blog.csdn.net/huilan_same/article/details/52944782 unittest是xUnit系列框架中的一员,如果你了解xUnit的其他成员,那 ...

  7. opencv笔记--HOGDescriptor

    特征描述提取图像区域上有用信息而忽略无用信息,不同目标下有用信息与无用信息定义不同.这里提取的有用信息用于分类器输入并期望产生正确的分类. HOG(Histogram of Oriented Grad ...

  8. php使用CURL进行模拟登录采集数据

    <?php $cookie_path = './'; //设置cookie保存路径 //-----登录要提交的表单数据--------------- $vars['username'] = '张 ...

  9. LibOpenCM3(五) 基础功能: 系统时钟, GPIO, 定时器

    目录 LibOpenCM3(一) Linux下命令行开发环境配置 LibOpenCM3(二) 项目模板 Makefile分析 LibOpenCM3(三) .ld文件(连接器脚本)和startup代码说 ...

  10. go 互斥锁实现原理

    目录 go 互斥锁的实现 1. mutex的数据结构 1.1 mutex结构体,抢锁解锁原理 1.2 mutex方法 2. 加解锁过程 2.1 简单加锁 2.2 加锁被阻塞 2.3 简单解锁 2.4 ...