c# 批量注册接口和服务,示例代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
using Microsoft.Extensions.DependencyInjection;using System;using System.Linq;using System.Reflection;// 自定义属性来标记服务类型[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]public class ServiceTypeAttribute : Attribute{ public ServiceLifetime Lifetime { get; } public ServiceTypeAttribute(ServiceLifetime lifetime) { Lifetime = lifetime; }}public static class DependencyInjectionExtensions{ /// <summary> /// 批量注册服务 /// </summary> /// <param name="services">IServiceCollection</param> /// <param name="servicePrefix">服务类的前缀,例如 "Service"</param> /// <param name="interfacePrefix">接口的前缀,例如 "I"</param> public static void RegisterServices(this IServiceCollection services, string servicePrefix, string interfacePrefix) { if (services == null) { throw new ArgumentNullException(nameof(services)); } // 获取当前程序集中所有类 var types = Assembly.GetExecutingAssembly().GetTypes(); // 筛选出符合服务命名约定的类 var serviceTypes = types .Where(t => t.Name.StartsWith(servicePrefix) && !t.IsInterface && !t.IsAbstract) .ToList(); // 遍历所有服务类 foreach (var serviceType in serviceTypes) { // 尝试查找对应的接口 var interfaceType = types.FirstOrDefault(t => t.Name == interfacePrefix + serviceType.Name.Substring(servicePrefix.Length) && t.IsInterface); if (interfaceType != null) { // 获取服务类型上的 ServiceTypeAttribute var serviceTypeAttribute = serviceType.GetCustomAttribute<ServiceTypeAttribute>(); var lifetime = serviceTypeAttribute?.Lifetime ?? ServiceLifetime.Scoped; // 默认使用 Scoped // 根据不同的生命周期注册服务 switch (lifetime) { case ServiceLifetime.Singleton: services.AddSingleton(interfaceType, serviceType); break; case ServiceLifetime.Scoped: services.AddScoped(interfaceType, serviceType); break; case ServiceLifetime.Transient: services.AddTransient(interfaceType, serviceType); break; default: services.AddScoped(interfaceType, serviceType); // 默认使用 Scoped break; } } else { // 如果没有找到对应的接口,则可以选择只注册服务本身,或者抛出异常 // 这里选择抛出异常,提示开发者需要有对应的接口 throw new InvalidOperationException($"Service {serviceType.Name} does not have a corresponding interface (expected interface name: {interfacePrefix}{serviceType.Name.Substring(servicePrefix.Length)})"); } } }}// 示例接口和服务public interface IUserService{ void DoSomething();}[ServiceType(ServiceLifetime.Scoped)] // 使用属性标记生命周期public class UserService : IUserService{ public void DoSomething() { Console.WriteLine("UserService.DoSomething() called."); }}public interface IOrderService{ void ProcessOrder();}[ServiceType(ServiceLifetime.Transient)]public class OrderService: IOrderService{ public void ProcessOrder() { Console.WriteLine("OrderService.ProcessOrder() called."); }}public class Program{ public static void Main(string[] args) { // 创建 ServiceCollection IServiceCollection services = new ServiceCollection(); // 注册服务 services.RegisterServices("Service", "I"); // 添加其他必要的服务,例如 MVC services.AddMvc(); // 如果是 ASP.NET Core MVC 项目 // 构建 ServiceProvider IServiceProvider serviceProvider = services.BuildServiceProvider(); // 从 ServiceProvider 中获取服务并使用 var userService = serviceProvider.GetService<IUserService>(); userService?.DoSomething(); var orderService = serviceProvider.GetService<IOrderService>(); orderService?.ProcessOrder(); Console.ReadKey(); }} |
代码说明
- ServiceTypeAttribute: 这是一个自定义属性,用于显式指定服务类的生命周期(Singleton、Scoped 或 Transient)。
- RegisterServices 扩展方法:
- 它扩展了
IServiceCollection,提供了一个便捷的方法来批量注册服务。 servicePrefix参数指定服务类的前缀(例如,"Service")。interfacePrefix参数指定接口的前缀(例如,"I")。- 它使用反射来查找程序集中所有符合命名约定的类(例如,以 "Service" 开头的类)。
- 它假定接口的命名约定是接口前缀 + 服务类名(去掉服务前缀)。 例如,如果服务类是
UserService,则对应的接口应该是IUserService。 - 它使用
GetCustomAttribute方法获取服务类上的ServiceTypeAttribute属性,并根据属性中指定的生命周期注册服务。 如果未找到此属性,则默认使用Scoped生命周期。 - 如果找不到与服务类对应的接口,它会抛出一个异常,指示缺少必需的接口。
- 它扩展了
- 示例:
IUserService和UserService演示了如何定义一个服务及其接口。IOrderService和OrderService演示了另一个服务及其接口,并使用[ServiceType]特性标记了生命周期- 在
Main方法中,我们创建了一个ServiceCollection,调用RegisterServices方法注册服务,然后从ServiceProvider中解析并使用这些服务。
使用说明
- 定义您的服务接口和服务类,并确保它们遵循命名约定(例如,
IUserService和UserService)。 - 使用
ServiceTypeAttribute属性标记您的服务类,以指定其生命周期。 如果省略此属性,则默认使用Scoped生命周期。 - 在您的应用程序的启动配置中(例如,
Main方法或ConfigureServices方法中),获取IServiceCollection的实例,并调用RegisterServices扩展方法,传递服务类前缀和接口前缀。 - 像往常一样使用依赖注入来获取服务实例。
这个方法提供了一种灵活且类型安全的方式来批量注册服务,并允许您通过属性显式控制每个服务的生命周期。
2025-05-09 16:22:39【出处】:https://www.cnblogs.com/wwwan/p/18868271
=======================================================================================
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。(●'◡'●)
因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/18868435
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
浙公网安备 33010602011771号