时间:2025-05-09 15:23
人气:
作者:admin
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();
}
}
代码说明
IServiceCollection,提供了一个便捷的方法来批量注册服务。servicePrefix 参数指定服务类的前缀(例如,"Service")。interfacePrefix 参数指定接口的前缀(例如,"I")。UserService,则对应的接口应该是 IUserService。GetCustomAttribute 方法获取服务类上的 ServiceTypeAttribute 属性,并根据属性中指定的生命周期注册服务。 如果未找到此属性,则默认使用 Scoped 生命周期。IUserService 和 UserService 演示了如何定义一个服务及其接口。IOrderService 和 OrderService 演示了另一个服务及其接口,并使用[ServiceType] 特性标记了生命周期Main 方法中,我们创建了一个 ServiceCollection,调用 RegisterServices 方法注册服务,然后从 ServiceProvider 中解析并使用这些服务。使用说明
IUserService 和 UserService)。ServiceTypeAttribute 属性标记您的服务类,以指定其生命周期。 如果省略此属性,则默认使用 Scoped 生命周期。Main 方法或 ConfigureServices 方法中),获取 IServiceCollection 的实例,并调用 RegisterServices 扩展方法,传递服务类前缀和接口前缀。这个方法提供了一种灵活且类型安全的方式来批量注册服务,并允许您通过属性显式控制每个服务的生命周期。
Microsoft Agent Framework Skills 执行 Scripts(实
EF Core 原生 SQL 实战:FromSql、SqlQuery 与对