.NET 使用自带 DI 批量注入服务(Service)和 后台服务(BackgroundService)
builder.Services.AddHostedService<ClearLogTask>();
builder.Services.AddTransient<IOperationTransient, Operation>();
builder.Services.AddScoped<IOperationScoped, Operation>();
builder.Services.AddSingleton<IOperationSingleton, Operation>();
builder.Services.AddSingleton(new Operation());
builder.Services.AddScoped(typeof(Operation));
builder.Services.AddTransient(typeof(Operation));
builder.Services.AddSingleton(new Operation());
builder.Services.AddSingleton(typeof(Operation));
builder.Services.AddScoped(typeof(Operation));
builder.Services.AddTransient(typeof(Operation));
builder.Services.AddSingleton(new Operation("参数1","参数2"));
public static class IServiceCollectionExtension
{ public static void BatchRegisterServices(this IServiceCollection services)
{
var allAssembly = GetAllAssembly(); services.RegisterServiceByAttribute(ServiceLifetime.Singleton, allAssembly);
services.RegisterServiceByAttribute(ServiceLifetime.Scoped, allAssembly);
services.RegisterServiceByAttribute(ServiceLifetime.Transient, allAssembly); services.RegisterBackgroundService(allAssembly);
} /// <summary>
/// 通过 ServiceAttribute 批量注册服务
/// </summary>
/// <param name="services"></param>
/// <param name="serviceLifetime"></param>
private static void RegisterServiceByAttribute(this IServiceCollection services, ServiceLifetime serviceLifetime, List<Assembly> allAssembly)
{ List<Type> types = allAssembly.SelectMany(t => t.GetTypes()).Where(t => t.GetCustomAttributes(typeof(ServiceAttribute), false).Length > 0 && t.GetCustomAttribute<ServiceAttribute>()?.Lifetime == serviceLifetime && t.IsClass && !t.IsAbstract).ToList(); foreach (var type in types)
{ Type? typeInterface = type.GetInterfaces().FirstOrDefault(); if (typeInterface == null)
{
//服务非继承自接口的直接注入
switch (serviceLifetime)
{
case ServiceLifetime.Singleton: services.AddSingleton(type); break;
case ServiceLifetime.Scoped: services.AddScoped(type); break;
case ServiceLifetime.Transient: services.AddTransient(type); break;
}
}
else
{
//服务继承自接口的和接口一起注入
switch (serviceLifetime)
{
case ServiceLifetime.Singleton: services.AddSingleton(typeInterface, type); break;
case ServiceLifetime.Scoped: services.AddScoped(typeInterface, type); break;
case ServiceLifetime.Transient: services.AddTransient(typeInterface, type); break;
}
} } } /// <summary>
/// 注册后台服务
/// </summary>
/// <param name="services"></param>
/// <param name="serviceLifetime"></param>
private static void RegisterBackgroundService(this IServiceCollection services, List<Assembly> allAssembly)
{ List<Type> types = allAssembly.SelectMany(t => t.GetTypes()).Where(t => typeof(BackgroundService).IsAssignableFrom(t) && t.IsClass && !t.IsAbstract).ToList(); foreach (var type in types)
{
services.AddSingleton(typeof(IHostedService), type);
}
} /// <summary>
/// 获取全部 Assembly
/// </summary>
/// <returns></returns>
private static List<Assembly> GetAllAssembly()
{ var allAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList(); HashSet<string> loadedAssemblies = new(); foreach (var item in allAssemblies)
{
loadedAssemblies.Add(item.FullName!);
} Queue<Assembly> assembliesToCheck = new();
assembliesToCheck.Enqueue(Assembly.GetEntryAssembly()!); while (assembliesToCheck.Any())
{
var assemblyToCheck = assembliesToCheck.Dequeue();
foreach (var reference in assemblyToCheck!.GetReferencedAssemblies())
{
if (!loadedAssemblies.Contains(reference.FullName))
{
var assembly = Assembly.Load(reference); assembliesToCheck.Enqueue(assembly); loadedAssemblies.Add(reference.FullName); allAssemblies.Add(assembly);
}
}
} return allAssemblies;
} } [AttributeUsage(AttributeTargets.Class)]
public class ServiceAttribute : Attribute
{
public ServiceLifetime Lifetime { get; set; } = ServiceLifetime.Transient; }
[Service(Lifetime = ServiceLifetime.Scoped)]
[Service(Lifetime = ServiceLifetime.Singleton)]
[Service(Lifetime = ServiceLifetime.Transient)]
像下面的 AuthorizeService 只要只要在头部加上 [Service(Lifetime = ServiceLifetime.Scoped)]
[Service(Lifetime = ServiceLifetime.Scoped)]
public class AuthorizeService
{ private readonly DatabaseContext db;
private readonly SnowflakeHelper snowflakeHelper;
private readonly IConfiguration configuration; public AuthorizeService(DatabaseContext db, SnowflakeHelper snowflakeHelper, IConfiguration configuration)
{
this.db = db;
this.snowflakeHelper = snowflakeHelper;
this.configuration = configuration;
} /// <summary>
/// 通过用户id获取 token
/// </summary>
/// <param name="userId"></param>
/// <returns></returns>
public string GetTokenByUserId(long userId)
{
//此处省略业务逻辑
} }
至于注册后台服务,则连装饰属性都不需要加,如下面的的一个后台服务示例代码
public class ClearLogTask : BackgroundService
{ private readonly IServiceProvider serviceProvider; public DemoTask(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
} protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
return Task.Run(() =>
{
var timer = new Timer(1000 * 5);
timer.Elapsed += TimerElapsed;
timer.Start();
}, stoppingToken);
} private void TimerElapsed(object? sender, ElapsedEventArgs e)
{
//省略业务逻辑
}
}
builder.Services.BatchRegisterServices();
.NET 使用自带 DI 批量注入服务(Service)和 后台服务(BackgroundService)的更多相关文章
- .netcore之DI批量注入(支持泛型) - xms
一旦系统内模块比较多,按DI标准方法去逐个硬敲AddScoped/AddSingleton/AddTransient缺乏灵活性且效率低下,所以批量注入提供了很大的便捷性,特别是对于泛型的服务类,下面介 ...
- 利用ASP.netCore自带DI(DependencyInjection)实现批量依赖注入
ASP.net Core自带DI(依赖注入),用法如下: services.AddScoped(typeof(IProductService), typeof(ProductService)); 如果 ...
- Android系统编程入门系列之服务Service齐头并进多线程任务
在上篇文章中初步了解了Android系统的四大组件之一的服务Service,在服务内可以执行无用户交互的耗时操作任务,但是包括之前关于界面系列文章在内,生命周期方法都是在主线程内被系统回调的.如果直接 ...
- ASP.NET Core Web 应用程序系列(三)- 在ASP.NET Core中使用Autofac替换自带DI进行构造函数和属性的批量依赖注入(MVC当中应用)
在上一章中主要和大家分享了在ASP.NET Core中如何使用Autofac替换自带DI进行构造函数的批量依赖注入,本章将和大家继续分享如何使之能够同时支持属性的批量依赖注入. 约定: 1.仓储层接口 ...
- ASP.NET Core Web 应用程序系列(二)- 在ASP.NET Core中使用Autofac替换自带DI进行批量依赖注入(MVC当中应用)
在上一章中主要和大家分享在MVC当中如何使用ASP.NET Core内置的DI进行批量依赖注入,本章将继续和大家分享在ASP.NET Core中如何使用Autofac替换自带DI进行批量依赖注入. P ...
- 从我做起[原生DI实现模块化和批量注入].Net Core 之一
实现模块化注册 .Net Core实现模块化批量注入 我将新建一个项目从头开始项目名称Sukt.Core. 该项目分层如下: Sukt.Core.API 为前端提供APi接口(里面尽量不存在业务逻辑, ...
- 在.NET Core中批量注入Grpc服务
GRPC 是谷歌发布的一个开源.高性能.通用RPC服务,尽管大部分 RPC 框架都使用 TCP 协议,但其实 UDP 也可以,而 gRPC 干脆就用了 HTTP2.还有就是它具有跨平台.跨语言 等特性 ...
- .netCore2.0 程序集DI依赖注入
传统的依赖注入确实简单,但是随着项目的扩展随之而来的问题又来了,因为传统的注入是单个类和接口注入的,加入项目的接口和类增加到了上百个的话,就需要在Startup.cs中复制注入上百次,虽然能解决问题, ...
- IoC控制反转与DI依赖注入
IoC控制反转与DI依赖注入 IoC: Inversion of Control IoC是一种模式.目的是达到程序的复用.下面的两篇论文是对IoC的权威解释: InversionOfControl h ...
随机推荐
- Metalama简介5.配合VisualStudio自定义重构或快速操作功能
使用基于Roslyn的编译时AOP框架来解决.NET项目的代码复用问题 Metalama简介1. 不止是一个.NET跨平台的编译时AOP框架 Metalama简介2.利用Aspect在编译时进行消除重 ...
- 实战|Hadoop大数据集群搭建
一个执着于技术的公众号 前言 今天来为粉丝圆梦啦 话不多说,咱直接进入实战环节 实验环境: 主机名 IP地址 角色 qll251 192.16 ...
- linux系统平均负载高(load average)
系统平均负载高(load average) 问题现象 两个案例都是:系统平均负载高,但cpu,内存,磁盘io都正常 什么是系统平均负载 平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进 ...
- socket模块和黏包问题
socket套接字简介 编写cs架构的程序 实现数据交互 OSI七层相当复杂 socket套接字是一门技术 socket模块>>>:提供了快捷方式 不需要自己处理每一层 " ...
- RabbitMQ从概念到使用、从Docker安装到RabbitMQ整合Springboot【1.5w字保姆级教学】
@ 目录 一.前言 二.RabbitMQ作用 1. 异步处理 2. 应用解耦 3. 流量控制 三.RabbitMQ概念 1. RabbitMQ简介 2. 核心概念 四.JMS与AMQP比较 五.Rab ...
- c++ :STL
基础知识 容器 容器就是一些模板类的集合,不同之处就是容器中封装的是数据结构 1.序列容器 主要有vector向量容器.list列表容器.deque双端队列容器 元素在容器中是无序的 2.排序容器 包 ...
- linux篇-rpm包安装mysql数据库
3.1上传以下两个rpm包到服务器上 MySQL-server-5.6.27-1.el6.x86_64.rpm MySQL-client-5.6.27-1.el6.x86_64.rpm 3.2卸载一个 ...
- debconf-utils-交互式安装时预配置
debconf-utils是一个可以在Ubuntu下预先配置要安装程序的小工具,它可以避免在安装一个DEB程序时的弹窗输入问题,这可能在编写一键部署脚本的时候非常有用. 以下我们用安装MySQL-AP ...
- kruskal 及其应用
kruskal 最小生成树 kruskal 是一种常见且好理解的最小生成树(MST)算法. 前置知识 并查集和路径压缩 生成树 在有 n 的顶点的无向图中,取其中 n-1 条边相连,所得到的树即为生成 ...
- Python中的逻辑表达式
首先要明确一点,Python的逻辑运算符,可以用来操作任何类型的表达式(不局限于Bool类型),且运算后的结果也不一定是Bool类型的,而是其左右其中一个表达式的值 表达式1 and 表达式2 pyt ...