Minimal API集成Kofax TotalAgility时依赖注入报错排查
问题描述
在Minimal API中集成Kofax TotalAgility的WCF端点时,启动服务遇到依赖注入解析失败的异常。
现有实现
服务接口
public interface IKofaxService { public Task<string> CreateJob(long letterId); public Task ActionHandler(PortalActionRequest request); }
服务实现
public class KofaxService : IKofaxService { private readonly ILogger<KofaxService> logger; private readonly KofaxSetup config; private readonly KtaJob.IJobService jobService; private readonly KtaActivity.IActivityService activityService; public KofaxService(ILogger<KofaxService> inLogger, KofaxSetup inConfig) { logger = inLogger; // 此处存在问题:构造函数参数应改为IOptions<KofaxSetup>,下方代码需改为config = inConfig.Value; config = inConfig; // 远程程序集中的WCF生成代码 jobService = new KtaJob.JobServiceClient(GetBinding(), GetEndpointAddress(config.KtaUrlApiJob)); activityService = new KtaActivity.ActivityServiceClient(GetBinding(), GetEndpointAddress(config.KtaUrlApiActivity)); } public async Task<string> CreateJob(long letterId) { ... } public async Task ActionHandler(PortalActionRequest request) { ... } }
服务扩展方法
public static class ServiceCollectionExtensions { public static IServiceCollection AddKofaxTotalAgility(this IServiceCollection services) { services.AddScoped<IKofaxService, KofaxService>(); return services; } }
配置类
public class KofaxSetup { public string KtaUrlApiActivity { get; set; } = string.Empty; public string KtaUrlApiJob { get; set; } = string.Empty; public string SessionId { get; set; } = string.Empty; public string ProcessId { get; set; } = string.Empty; }
appSettings.json配置
{ ... "KofaxSetup": { "KtaUrlApiActivity": "https://kofax.somewhere.com/TotalAgility/Services/SDK/ActivityService.svc", "KtaUrlApiJob": "https://kofax.somewhere.com/TotalAgility/Services/SDK/JobService.svc", "SessionId": "7DB87F70018D4770BF6114B1C9BA6041", "ProcessId": "66EC6EED5D024E7AB0013D60F7A04A1A" }, ... }
Program.cs配置
var builder = WebApplication.CreateBuilder(args); ... // 从AppSettings配置节绑定KofaxSetup对象 builder.Services.Configure<KofaxSetup>(builder.Configuration.GetSection(nameof(KofaxSetup))); ... // 将服务添加到依赖注入容器 builder.Services.AddKofaxTotalAgility(); ...
启动异常
System.AggregateException: 'Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: DACRL.Integrations.Kofax.IKofaxService Lifetime: Scoped ImplementationType: DACRL.Integrations.Kofax.KofaxService': Unable to resolve service for type 'DACRL.Integrations.Kofax.Configs.KofaxSetup' while attempting to activate 'DACRL.Integrations.Kofax.KofaxService'.) (Error while validating the service descriptor 'ServiceType: DACRL.Application.Core.Services.ILetterService Lifetime: Transient ImplementationType: DACRL.Api.Services.LetterService': Unable to resolve service for type 'DACRL.Integrations.Kofax.Configs.KofaxSetup' while attempting to activate 'DACRL.Integrations.Kofax.KofaxService'.) (Error while validating the service descriptor 'ServiceType: DACRL.Application.Core.Services.ILetterService Lifetime: Transient ImplementationType: DACRL.Api.Services.LetterService': Unable to resolve service for type 'DACRL.Integrations.Kofax.Configs.KofaxSetup' while attempting to activate 'DACRL.Integrations.Kofax.KofaxService'.)' 1/2: InvalidOperationException: Error while validating the service descriptor 'ServiceType: DACRL.Integrations.Kofax.IKofaxService Lifetime: Scoped ImplementationType: DACRL.Integrations.Kofax.KofaxService': Unable to resolve service for type 'DACRL.Integrations.Kofax.Configs.KofaxSetup' while attempting to activate 'DACRL.Integrations.Kofax.KofaxService'. 2/2: InvalidOperationException: Unable to resolve service for type 'DACRL.Integrations.Kofax.Configs.KofaxSetup' while attempting to activate 'DACRL.Integrations.Kofax.KofaxService'.
注:ILetterService运行正常,它通过依赖注入获取IKofaxService。怀疑问题出在KofaxSetup对象的注入上。
解决方案
核心问题
你在Program.cs里用Configure<KofaxSetup>注册的是IOptionsKofaxService的构造函数直接依赖KofaxSetup类型,DI容器无法解析这个类型,因为你没把KofaxSetup本身注册到容器里。
修复步骤
1. 修改KofaxService构造函数依赖(推荐方案)
按照你代码注释里的提示,把构造函数参数改成IOptions<KofaxSetup>,符合.NET配置的最佳实践:
public class KofaxService : IKofaxService { private readonly ILogger<KofaxService> logger; private readonly KofaxSetup config; private readonly KtaJob.IJobService jobService; private readonly KtaActivity.IActivityService activityService; public KofaxService(ILogger<KofaxService> inLogger, IOptions<KofaxSetup> inConfig) { logger = inLogger; config = inConfig.Value; // 从IOptions中获取配置实例 // 远程程序集中的WCF生成代码 jobService = new KtaJob.JobServiceClient(GetBinding(), GetEndpointAddress(config.KtaUrlApiJob)); activityService = new KtaActivity.ActivityServiceClient(GetBinding(), GetEndpointAddress(config.KtaUrlApiActivity)); } // 其他方法保持不变 }
2. 备选方案:直接注册KofaxSetup到DI容器
如果不想修改构造函数,可以在Program.cs里把KofaxSetup实例注册为单例:
var builder = WebApplication.CreateBuilder(args); ... var kofaxConfig = new KofaxSetup(); builder.Configuration.GetSection(nameof(KofaxSetup)).Bind(kofaxConfig); builder.Services.AddSingleton(kofaxConfig); ... builder.Services.AddKofaxTotalAgility(); ...
但这种方案不如IOptions灵活,无法支持配置重载、选项验证等高级特性,不推荐。
3. 优化扩展方法(可选)
为了让集成更流畅,可以把配置绑定逻辑整合到扩展方法里,减少主项目的代码:
public static class ServiceCollectionExtensions { public static IServiceCollection AddKofaxTotalAgility(this IServiceCollection services, IConfiguration configuration) { services.Configure<KofaxSetup>(configuration.GetSection(nameof(KofaxSetup))); services.AddScoped<IKofaxService, KofaxService>(); return services; } }
然后在Program.cs里调用:
builder.Services.AddKofaxTotalAgility(builder.Configuration);
关于Logger注入
Logger<KofaxService>的注入是有效的,Minimal API默认已配置日志服务,DI容器会自动解析这个类型,异常里也未提及Logger相关错误,所以问题不在此处。
无参构造函数?不需要
不要添加无参构造函数,这会破坏依赖注入的设计,且无法获取logger和配置实例,完全没必要。
内容的提问来源于stack exchange,提问作者DoomerDGR8
相关产品推荐
相关产品推荐

