最近写一个接口对接平台, 为了灵活和减少代码开发工作量.
需要做成可配置的.
可配置就意味着动态性, 代码不是写死的.
大致把接口形式分为了两种, 一种是主动的, 一种是被动的.
主动的接口是指: 由 我方 系统主动发起调用 对方 的webapi
被动的接口是指: 由 对方 系统主动发起调用 我方 的webapi
本文主要讲的是主动接口, 主动类型的接口多数是由定时器触发的.
那么, 这种类型的接口.在asp.net core 中如何实现呢?
方案不止一种.
一种方案是第三方的Quartz.Net 和
另外一种方案是 自己用 Microsoft.Extensions.Hosting.IHostedService 加Timer 自己写一个简单的定时器. 而且是长期循环执行的这种.
考虑到简单灵活,满足要求就够的 编程风格. 还是打算自己弄一个.
当然这篇文章里不牵扯到具体的持久化, 这个需要按照自己的项目需求去配置.
关于 IHostedService 和 BackgroundService 需要自己百度一下. 相关说明.
其实还算简单的.主要是两个类
BackgroundServicesHelper.cs
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
namespace WSI.BackgroundServices
{
public static class BackgroundServicesHelper
{
/// <summary>
/// 反射取得所有的业务逻辑类
/// </summary>
private static Type[] GetAllChildClass( Type baseType)
{
var types = AppDomain.CurrentDomain.GetAssemblies()
//取得实现了某个接口的类
//.SelectMany(a => a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(ISecurity)))) .ToArray();
//取得继承了某个类的所有子类
.SelectMany(a => a.GetTypes().Where(t => t.BaseType == baseType))
.ToArray();
return types;
}
public static Type[] GetAllBackgroundService( )
{
return GetAllChildClass(typeof(BackgroundService));
}
/// <summary>
/// 自动增加后台任务.所有继承自BackgroundService的类都会自动运行
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public static IServiceCollection AddBackgroundServices(this IServiceCollection services)
{
//services.AddHostedService<TimedService>(); //asp.net core 应该是这个.
//或者 单为方便循环自动创建, 所以改成使用AddTransient 也一样可以使用.
//services.AddTransient<IHostedService, TimedService>();
//services.AddTransient(typeof(Microsoft.Extensions.Hosting.IHostedService),backtype);
//var backtypes = BackgroundServicesHelper.GetAllBackgroundService();
//foreach (var backtype in backtypes)
//{
// services.AddTransient(typeof(Microsoft.Extensions.Hosting.IHostedService),backtype);
//}
var backtypes = GetAllBackgroundService();
foreach (var backtype in backtypes)
{
services.AddTransient(typeof(Microsoft.Extensions.Hosting.IHostedService), backtype);
}
return services;
}
}
}
再创建一个具体干活的服务类. 这个类是用来执行具体任务的.
TimedService.cs
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace WSI.BackgroundServices
{
/// <summary>
/// 定时任务触发器
/// </summary>
public class TimedService : BackgroundService
{
/**
*
需要在Startup.cs 里面注册
* public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<TimedService>();
或者
services.AddTransient<IHostedService, TimedService>();
}
* */
private readonly ILogger _logger;
//private Timer _timer;
public TimedService(ILogger<TimedService> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("servers startA");
while (!stoppingToken.IsCancellationRequested)
{
//执行任务
_logger.LogInformation("TimedServiceA DoWork");
await Task.Delay(5000, stoppingToken); //延迟暂停5秒
}
_logger.LogInformation("servers end");
}
public override void Dispose()
{
base.Dispose();
}
}
}
还可以写更多个
TimedServiceA,
TimedServiceB,
只要继承自BackgroundService 就可以了.
最后 使用的时候还需要在
startup.cs
中增加一行
public void ConfigureServices(IServiceCollection services)
{
..........
//自动注入定时器开始,//后台任务启动专用.
services.AddBackgroundServices();
//自动注入定时器结束,
..........
}
本篇文章主要重点是 AddBackgroundServices() 里面的动态创建 Services的方法
这一行.
services.AddTransient(typeof(Microsoft.Extensions.Hosting.IHostedService), backtype);