.NET6 Azure Function泛型Handler依赖注入问题求助
解决方案
方案一:引入非泛型基接口统一委托类型
核心思路是通过非泛型接口作为委托的返回类型,避免注册时必须指定未知的泛型参数T,同时保留泛型方法的类型安全。
1. 调整接口定义
新增非泛型的ISvcMessageHandler接口,让泛型版本继承它:
// 基础非泛型接口 public interface ISvcMessageHandler : IHandler { Task<object> ReturnObjectAsync(IMessage message, CancellationToken cancellationToken); } // 泛型接口,继承自非泛型版本 public interface ISvcMessageHandler<T> : ISvcMessageHandler where T : class { // 用new关键字覆盖非泛型方法,保留强类型返回 new Task<List<T>> ReturnObjectAsync(IMessage message, CancellationToken cancellationToken); }
2. 实现泛型Handler
在实现类中显式实现非泛型接口的方法,内部调用泛型方法:
public class HandleA : ISvcMessageHandler<DtoA> { // 实现泛型接口的强类型方法 public async Task<List<DtoA>> ReturnObjectAsync(IMessage message, CancellationToken cancellationToken) { // 业务逻辑实现 return new List<DtoA>(); } // 显式实现非泛型接口的方法,转换返回类型 async Task<object> ISvcMessageHandler.ReturnObjectAsync(IMessage message, CancellationToken cancellationToken) { return await ReturnObjectAsync(message, cancellationToken); } // 保留原IHandler的HandleAsync方法(如果需要兼容旧逻辑) public async Task HandleAsync(IMessage message, CancellationToken cancellationToken) { // 可选:调用新的泛型方法或保留原有逻辑 await ReturnObjectAsync(message, cancellationToken); } } // HandleB同理实现ISvcMessageHandler<DtoB>
3. 注册委托
现在可以注册返回非泛型ISvcMessageHandler的委托,无需指定T:
services.AddScoped<Func<MessageType, ISvcMessageHandler>>(sp => dataType => { return dataType switch { MessageType.HandleA => sp.GetRequiredService<HandleA>(), MessageType.HandleB => sp.GetRequiredService<HandleB>(), _ => throw new ArgumentOutOfRangeException(nameof(dataType), dataType, "不支持的消息类型") }; });
4. 调用Handler
在业务逻辑中,根据MessageType获取handler后,转换为对应的泛型类型处理:
// 注入Func<MessageType, ISvcMessageHandler> private readonly Func<MessageType, ISvcMessageHandler> _handlerFactory; public MyService(Func<MessageType, ISvcMessageHandler> handlerFactory) { _handlerFactory = handlerFactory; } public async Task ProcessMessage(IMessage message, MessageType messageType, CancellationToken cancellationToken) { var handler = _handlerFactory(messageType); // 根据消息类型转换为对应泛型handler if (handler is ISvcMessageHandler<DtoA> aHandler) { List<DtoA> result = await aHandler.ReturnObjectAsync(message, cancellationToken); // 处理DtoA结果 } else if (handler is ISvcMessageHandler<DtoB> bHandler) { List<DtoB> result = await bHandler.ReturnObjectAsync(message, cancellationToken); // 处理DtoB结果 } }
方案二:使用专用工厂类封装类型逻辑
如果希望调用时更简洁,可以创建工厂类,封装根据MessageType和泛型参数获取Handler的逻辑。
1. 创建工厂类
public class MessageHandlerFactory { private readonly IServiceProvider _serviceProvider; public MessageHandlerFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public ISvcMessageHandler<T> GetHandler<T>(MessageType messageType) where T : class { return messageType switch { MessageType.HandleA => _serviceProvider.GetRequiredService<HandleA>() as ISvcMessageHandler<T>, MessageType.HandleB => _serviceProvider.GetRequiredService<HandleB>() as ISvcMessageHandler<T>, _ => throw new ArgumentOutOfRangeException(nameof(messageType), "不支持的消息类型") }; } }
2. 注册工厂
services.AddScoped<MessageHandlerFactory>();
3. 调用工厂
调用时直接指定泛型参数和MessageType:
// 注入MessageHandlerFactory private readonly MessageHandlerFactory _handlerFactory; public MyService(MessageHandlerFactory handlerFactory) { _handlerFactory = handlerFactory; } public async Task ProcessDtoAMessage(IMessage message, CancellationToken cancellationToken) { var handler = _handlerFactory.GetHandler<DtoA>(MessageType.HandleA); List<DtoA> result = await handler.ReturnObjectAsync(message, cancellationToken); // 处理结果 }
内容的提问来源于stack exchange,提问作者macm
相关产品推荐
相关产品推荐

