.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 ...
随机推荐
- 1.5 Linux中大量使用脚本语言,而不是C语言!
说到在 Linux 下的编程,很多人会想到用C语言,Linux 的内核.shell.基础命令程序,也的确是用C语言编写的,这首先证明了一点,C语言很强很通用. 到目前为止,C语言依然垄断着计算机工业中 ...
- 【Python情感分析】用python情感分析李子柒频道视频热门评论
一.事件背景 今天是2021.12.2日,距离李子柒断更已经4个多月了,这是我在YouTube李子柒油管频道上,观看李子柒2021年7月14日上传的最后一条视频,我录制了视频下方的来自全世界各国网友的 ...
- Web3.0应用程序架构
Web 3.0 应用程序(或"DApps")的架构与 Web 2.0 应用程序完全不同. 以博客园为例,这是一个简洁的博客网站,用户可以发布自己的内容并可以评论他人的内容进行互动. ...
- this 去哪?
this 去哪? 本文写于 2020 年 4 月 26 日 let obj = { foo() { console.log(this) }, } let bar = obj.foo obj.foo() ...
- 以圆类 Circle 及立体图形类 Solid 为基础设计圆柱类 Cylinder
学习内容:以圆类 Circle 及立体图形类 Solid 为基础设计圆柱类 Cylinder 代码示例: import java.util.Scanner;class Point3{ private ...
- 联盟链 Hyperledger Fabric 应用场景
一.说明 本文主要通过一个例子分享以 Hyperledger Fabric 为代表的联盟链应用场景. 关于 Fabric 的相关概念请先参考文章 <Hyperledger Fabric 核心概念 ...
- Map和WeakMap的方法和区别
Map Map是一组键值对的结构,具有极快的查找速度. 一.构造函数不同 let map = new Map(); let weakmap = new WeakMap(); 二.内置函数不同 Map的 ...
- K8S Flannel网络插件
0.前言 参考文档:https://github.com/containernetworking/cni Pod网络插件,为了实现Pod网络而需要的插件.组件.由于Kubernetes通过开放的CNI ...
- 纯CSS如何禁止用户复制网页的内容?
大家好,我是半夏,一个刚刚开始写文的沙雕程序员.如果喜欢我的文章,可以关注 点赞 加我微信:frontendpicker,一起学习交流前端,成为更优秀的工程师-关注公众号:搞前端的半夏,了解更多前端知 ...
- JAVA - 缓冲和缓存
JAVA - 缓冲和缓存 缓冲 Buffer 功能:协调上下层应用之间的性能差异.通过缓冲区的缓冲,当上层组件性能优于下层组件的时候,缓冲可以有效减少上层组件对下层组件的等待时间. 使用场景:IO流中 ...