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

.NET 6 WebAPI实现策略模式时触发System.InvalidOperationException异常

策略模式结合依赖注入的问题排查与解决

核心结论

完全可以通过依赖注入实现策略模式,你遇到的错误是因为具体策略类未在DI容器中注册,或者工厂尝试获取的类型与注册方式不匹配。

常见错误原因

你大概率只注册了ISyncStrategy到具体类的映射,比如:

// 错误示例:仅注册接口到实现,未注册具体类本身
services.AddScoped<ISyncStrategy, CompanySyncStrategy>();
services.AddScoped<ISyncStrategy, ProjectSyncStrategy>();

这种情况下,DI容器知道如何通过ISyncStrategy获取实例,但无法直接解析CompanySyncStrategy这个具体类型——而你的SyncStrategyFactory可能正尝试直接获取该具体类型,因此抛出未注册的异常。

正确的解决方式

方式1:显式注册具体策略类

在Program.cs中同时注册具体类和接口映射:

// 注册具体策略类
services.AddScoped<CompanySyncStrategy>();
services.AddScoped<ProjectSyncStrategy>();

// 可选:注册接口到实现的映射(如果需要通过ISyncStrategy直接获取)
services.AddScoped<ISyncStrategy>(sp => sp.GetRequiredService<CompanySyncStrategy>());

之后工厂就可以通过IServiceProvider直接获取具体类型的实例。

方式2:使用键控服务(.NET 8+推荐)

如果你的策略需要按标识区分,推荐使用.NET 8引入的键控服务,更贴合策略模式的场景:

// 按键注册策略
services.AddKeyedScoped<ISyncStrategy, CompanySyncStrategy>("company");
services.AddKeyedScoped<ISyncStrategy, ProjectSyncStrategy>("project");

对应的工厂实现:

public class SyncStrategyFactory
{
    private readonly IServiceProvider _serviceProvider;

    public SyncStrategyFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public ISyncStrategy GetStrategy(string strategyKey)
    {
        return strategyKey switch
        {
            "company" => _serviceProvider.GetRequiredKeyedService<ISyncStrategy>("company"),
            "project" => _serviceProvider.GetRequiredKeyedService<ISyncStrategy>("project"),
            _ => throw new ArgumentException($"Unknown strategy key: {strategyKey}")
        };
    }
}

记得把工厂也注册到DI:

services.AddScoped<SyncStrategyFactory>();

方式3:通过反射批量注册(进阶)

如果策略类较多,可以通过反射批量注册所有实现ISyncStrategy的类型:

var strategyTypes = Assembly.GetExecutingAssembly()
    .GetTypes()
    .Where(t => typeof(ISyncStrategy).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);

foreach (var type in strategyTypes)
{
    services.AddScoped(type);
    services.AddScoped(typeof(ISyncStrategy), type);
}

额外注意事项

  • 确保SyncStrategyFactory本身已被注册到DI容器,并且通过构造函数注入IServiceProvider(或直接注入所需策略类的集合)。
  • 避免在工厂中直接实例化策略类,务必通过DI容器获取,保证策略类的依赖也能被正确注入。

内容的提问来源于stack exchange,提问作者Ayesh Silva

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 22:36:12