You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:12:46