.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 ...
随机推荐
- go thrift 开发
thrift 从 0.9.1版本开始,可以完美支持 go 语言,可以完美的实现跨语言的 rpc 调用了.下面以 go 和 java 语言相互调用为例. 编辑协议文件,go 语言示例 /** examp ...
- 简易版 vue实现
Vue-mini 完整的Demo示例:git@github.com:xsk-walter/Vue-mini.git 一.Vue实例 构造函数: $option\ $el\ $data 判断是否存在 通 ...
- L2M-GAN: Learning to Manipulate Latent Space Semantics for Facial Attribute Editing阅读笔记
L2M-GAN: Learning to Manipulate Latent Space Semantics for Facial Attribute Editing 2021 CVPR L2M-GA ...
- 个人冲刺(六)——体温上报app(二阶段)
冲刺任务:完成主页面功能 MainActivity.java package com.example.helloworld; import android.app.AlertDialog; impor ...
- 深度学习可视化工具--tensorboard的使用
tensorboard的使用 官方文档 # writer.add_scalar() # 添加标量 """ Args: tag (string): Data identif ...
- 声学感知刻度(mel scale、Bark scale、ERB)与声学特征提取(MFCC、BFCC、GFCC)
梅尔刻度 梅尔刻度(Mel scale)是一种由听众判断不同频率 音高(pitch)彼此相等的感知刻度,表示人耳对等距音高(pitch)变化的感知.mel 刻度和正常频率(Hz)之间的参考点是将1 k ...
- Python趣味入门9:函数是你走过的套路,详解函数、调用、参数及返回值
1.概念 琼恩·雪诺当上守夜人的司令后,为训练士兵对付僵尸兵团,把成功斩杀僵尸的一系列动作编排成了"葵花宝典剑法",这就是函数.相似,在计算机世界,一系列前后连续的计算机语句组合在 ...
- 深度学习与CV教程(4) | 神经网络与反向传播
作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/37 本文地址:http://www.showmeai.tech/article-det ...
- SpringSecurity简单入门
1.简介 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架.它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spr ...
- 【多线程与高并发原理篇:4_深入理解synchronized】
1. 前言 越是简单的东西,在深入了解后发现越复杂.想起了曾在初中阶段,语文老师给我们解说<论语>的道理,顺便给我们提了一句,说老子的无为思想比较消极,学生时代不要太关注.现在有了一定的生 ...