ASP.NET WebApi中SimpleInjector Container.Verify()与Http上下文依赖问题
解决方案
1. 把Work的注册转到SimpleInjector容器,灵活控制验证行为
你当前用MSDI的AddScoped注册Work,但SimpleInjector本身提供了更灵活的注册和验证配置。直接在SimpleInjector里注册Work,然后可以选择跳过该类型的验证,或者只验证根服务(控制器):
// 在ConfigureServices中,MSDI配置完成后添加: container.Register<Work>(() => { var accessor = container.GetInstance<IHttpContextAccessor>(); var traceId = accessor.HttpContext!.TraceIdentifier; // 初始化Work实例 }, Lifestyle.Scoped); // 选项1:跳过Work的验证 container.Options.SuppressDependencyVerification<Work>(); // 选项2:只验证根服务(比如控制器),不深入验证依赖链 // container.Verify(VerificationOption.VerifyRootsOnly);
2. 延迟HttpContext的访问到Work内部(最推荐)
不要在注册工厂里直接取TraceIdentifier,而是把IHttpContextAccessor注入到Work类中,在实际执行业务逻辑的时候再访问HttpContext:
public class Work { private readonly IHttpContextAccessor _httpContextAccessor; public Work(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public void Execute() { // 这里确保在请求上下文内执行,HttpContext不会为null var traceId = _httpContextAccessor.HttpContext!.TraceIdentifier; // 业务逻辑 } }
然后注册的时候直接按类型注册即可:
// 用MSDI注册 services.AddScoped<Work>(); // 或者用SimpleInjector注册 // container.Register<Work>(Lifestyle.Scoped);
这样SimpleInjector验证的时候只会创建Work实例,不会调用Execute方法,自然不会触发HttpContext的访问,也就不会报错。而你可以保证Execute只会在请求期间被调用,此时HttpContext必然存在,用!空原谅运算符即可,不用额外做null判断——如果真的出现null,那就是基础设施故障,应该直接抛出异常快速暴露问题,而不是返回假实例掩盖问题。
3. 验证时临时模拟HttpContext(不推荐)
如果一定要保留原来的工厂注册方式,可以在Verify之前临时设置一个假的HttpContext:
public void Configure(IApplicationBuilder app) { app.ApplicationServices.UseSimpleInjector(container); // 临时设置模拟HttpContext用于验证 var accessor = container.GetInstance<IHttpContextAccessor>(); accessor.HttpContext = new DefaultHttpContext(); container.Verify(); // 验证后清空 accessor.HttpContext = null; // 其他中间件配置 }
这个方法比较hack,因为验证用的实例和实际请求的不一致,可能隐藏潜在问题,所以只作为临时 workaround。
内容的提问来源于stack exchange,提问作者Drew
相关产品推荐
相关产品推荐

