如何在MS DI中注册支持逆变的IActionHandler泛型实现?
解决MS DI中逆变IActionHandler注册问题
首先明确:由于IActionHandler<in T>是逆变接口,IActionHandler<SoftwareAction>无法直接向上转换为IActionHandler<IAction>(逆变允许的是从更宽泛的类型转向更具体的类型,比如IActionHandler<IAction>可以赋值给IActionHandler<SoftwareAction>,反之不行),所以直接注册成IActionHandler<IAction>会编译报错。
根据业务需求,分两种场景给出解决方案:
场景1:按具体Action类型获取对应Handler
如果业务逻辑是针对SoftwareAction、HardwareAction等具体Action类型,需要获取对应的处理器,直接按具体泛型类型注册即可:
// 注册SoftwareActionHandler services.AddSingleton<IActionHandler<SoftwareAction>, SoftwareActionHandler>(); // 同理注册其他实现类 services.AddSingleton<IActionHandler<HardwareAction>, HardwareActionHandler>();
使用时直接通过具体类型注入:
public class SomeService { private readonly IActionHandler<SoftwareAction> _softwareHandler; public SomeService(IActionHandler<SoftwareAction> softwareHandler) { _softwareHandler = softwareHandler; } public void DoWork() { var action = new SoftwareAction(); _softwareHandler.Execute(action); } }
场景2:动态处理任意IAction实例(根据Action类型匹配Handler)
如果需要接收任意IAction实例,并自动找到对应的IActionHandler<T>执行,可通过工厂模式实现:
步骤1:注册所有Handler为各自的泛型接口
先按场景1的方式完成所有IActionHandler<T>实现的注册。
步骤2:实现Handler工厂类
public class ActionHandlerFactory { private readonly IServiceProvider _serviceProvider; public ActionHandlerFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public Status ExecuteAction(IAction action) { var actionType = action.GetType(); var handlerType = typeof(IActionHandler<>).MakeGenericType(actionType); var handler = _serviceProvider.GetService(handlerType); if (handler == null) { throw new InvalidOperationException($"未找到针对{actionType.Name}类型的处理器"); } return (Status)handlerType.GetMethod(nameof(IActionHandler<IAction>.Execute))!.Invoke(handler, new[] { action }); } }
步骤3:注册工厂类
services.AddSingleton<ActionHandlerFactory>();
使用方式
public class SomeService { private readonly ActionHandlerFactory _handlerFactory; public SomeService(ActionHandlerFactory handlerFactory) { _handlerFactory = handlerFactory; } public void ProcessAnyAction(IAction action) { var status = _handlerFactory.ExecuteAction(action); // 处理执行结果 } }
补充:开放泛型注册(适用于通用Handler场景)
如果所有IActionHandler<T>都基于同一个泛型实现类,比如:
public class GenericActionHandler<T> : IActionHandler<T> where T : IAction { public Status Execute(T action) { // 通用执行逻辑 } }
可直接注册开放泛型:
services.AddSingleton(typeof(IActionHandler<>), typeof(GenericActionHandler<>));
内容的提问来源于stack exchange,提问作者cogumel0
相关产品推荐
相关产品推荐

