依赖注入异常排查:已验证工厂方法仍报System.String解析错误
问题:依赖注入容器无法解析MyService的字符串参数
相关代码定义
MyService类
public class MyService : IMyService { private readonly string _version; public MyService(string version) { _version = version; } }
VersionedAssembly类
public class VersionedAssembly : IVersionedAssembly { public string Version { get; } = typeof(VersionedAssembly).Assembly.GetName().Version!.ToString(); }
服务注册代码
services.AddSingleton<IVersionedAssembly, VersionedAssembly>(); services.AddScoped<IMyService>(provider => { string version = provider.GetRequiredService<IVersionedAssembly>().Version; return new MyService(version); })
报错信息
System.InvalidOperationException: 'Unable to resolve service for type 'System.String' while attempting to activate 'MyService'.' at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type implementationType, CallSiteChain callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound) in /_/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/CallSiteFactory.cs:line 518
已尝试操作
- 简化注册代码为:
services.AddScoped<IMyService>(provider => new MyService("1")); - 在工厂方法的
string version = provider.GetRequiredService<IVersionedAssembly>()处添加断点,但断点未触发
解决方案
问题核心是DI容器并未使用你定义的工厂方法创建IMyService实例,而是尝试直接激活MyService类型,这说明你大概率在项目其他地方重复注册了IMyService或MyService,且该注册覆盖了你的工厂方法注册。
排查与修复步骤
检查重复注册:
- 全局搜索项目中所有
AddScoped<IMyService>、AddTransient<IMyService>、AddSingleton<IMyService>的代码,或是直接注册MyService的语句(如services.AddScoped<MyService>())。 - 若存在
services.AddScoped<IMyService, MyService>()这类注册,它会覆盖你的工厂方法注册——DI容器会以最后一次服务注册为准。
- 全局搜索项目中所有
调整注册顺序:
- 确保你的工厂方法注册是最后一个针对
IMyService的注册,避免被其他注册覆盖。
- 确保你的工厂方法注册是最后一个针对
验证注册有效性:
- 可在注册后通过以下代码确认工厂方法是否生效:
var descriptor = services.FirstOrDefault(d => d.ServiceType == typeof(IMyService)); // 检查descriptor.ImplementationFactory是否不为null,以此确认工厂方法已被正确注册
- 可在注册后通过以下代码确认工厂方法是否生效:
修复示例
删除或调整重复注册的代码,确保工厂方法注册在最后:
// 移除其他重复的IMyService注册语句 services.AddSingleton<IVersionedAssembly, VersionedAssembly>(); // 确保这是最后一个IMyService的注册 services.AddScoped<IMyService>(provider => { string version = provider.GetRequiredService<IVersionedAssembly>().Version; return new MyService(version); });
内容的提问来源于stack exchange,提问作者Tam Coton
相关产品推荐
相关产品推荐

