.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
相关产品推荐
相关产品推荐

