SimpleInjector注册两个IEnumerable<Type>实例报错求助
SimpleInjector中IMiddleware集合依赖注册问题解决
问题概述
使用SimpleInjector时触发配置无效错误:创建IMiddleware实例失败,LogContextMiddleware构造函数中controllerTypeExclusionList(类型IEnumerable<Type>)参数未注册。错误提示需通过Container.Collection.Register或Append注册集合,空集合也需注册。
现有注册逻辑中,两个中间件(LogContextMiddleware、AuthorizationMiddleware<AppToken>)需要不同的排除类型列表,无法共用同一IEnumerable<Type>实例。
解决方案
方案1:创建专属包装类区分依赖
通过定义不同的包装类,将各自的排除列表封装,避免类型依赖冲突:
- 定义包装类:
// 日志中间件专属排除列表包装 public class LogControllerExclusions { public IEnumerable<Type> Types { get; } public LogControllerExclusions(IEnumerable<Type> types) => Types = types; } // 授权中间件专属排除列表包装 public class AuthorizationControllerExclusions { public IEnumerable<Type> Types { get; } public AuthorizationControllerExclusions(IEnumerable<Type> types) => Types = types; }
- 修改中间件构造函数,依赖对应包装类:
public class LogContextMiddleware : IMiddleware { private readonly IEnumerable<Type> controllerTypeExclusionList; private readonly ILogger logger; public LogContextMiddleware(LogControllerExclusions exclusions, ILogger logger) { controllerTypeExclusionList = exclusions.Types; this.logger = logger; } // 中间件InvokeAsync逻辑... } // 同理修改AuthorizationMiddleware<AppToken>构造函数,依赖AuthorizationControllerExclusions
- 注册包装类与中间件:
// 注册日志排除列表实例 container.RegisterInstance(new LogControllerExclusions( new List<Type> { typeof(StatusController) })); // 注册授权排除列表实例 container.RegisterInstance(new AuthorizationControllerExclusions( new List<Type> { typeof(StatusController), typeof(PruebaSinAuthController) })); // 注册中间件 container.Register<LogContextMiddleware>(Lifestyle.Transient); container.Register<AuthorizationMiddleware<AppToken>>(Lifestyle.Transient);
方案2:使用条件注册(命名依赖)
借助SimpleInjector的RegisterConditional,根据目标消费类型注入对应集合:
// 注册两个不同的排除列表实例(带命名标识) var logExclusions = new List<Type> { typeof(StatusController) }; container.RegisterInstance<IEnumerable<Type>>(logExclusions, "LogExclusions"); var authExclusions = new List<Type> { typeof(StatusController), typeof(PruebaSinAuthController) }; container.RegisterInstance<IEnumerable<Type>>(authExclusions, "AuthExclusions"); // 为LogContextMiddleware指定注入日志排除列表 container.RegisterConditional( typeof(IEnumerable<Type>), ctx => ctx.GetInstance<IEnumerable<Type>>("LogExclusions"), c => c.Consumer.ImplementationType == typeof(LogContextMiddleware)); // 为AuthorizationMiddleware<AppToken>指定注入授权排除列表 container.RegisterConditional( typeof(IEnumerable<Type>), ctx => ctx.GetInstance<IEnumerable<Type>>("AuthExclusions"), c => c.Consumer.ImplementationType == typeof(AuthorizationMiddleware<AppToken>)); // 注册中间件 container.Register<LogContextMiddleware>(Lifestyle.Transient); container.Register<AuthorizationMiddleware<AppToken>>(Lifestyle.Transient);
方案3:让SimpleInjector接管中间件激活(推荐)
ASP.NET Core默认使用自身DI激活IMiddleware,替换为SimpleInjector的中间件工厂后,可确保依赖由SimpleInjector解析:
- 注册SimpleInjector中间件工厂:
container.Register<ISimpleInjectorMiddlewareFactory, SimpleInjectorMiddlewareFactory>(Lifestyle.Singleton);
- 在Program.cs中配置使用该工厂:
app.UseSimpleInjector(container); app.UseMiddleware<SimpleInjectorMiddlewareFactory>();
- 用条件注册为每个中间件绑定对应排除列表:
var logExclusions = new List<Type> { typeof(StatusController) }; container.RegisterConditional( typeof(IEnumerable<Type>), _ => InstanceProducer.ForInstance(logExclusions), c => c.Consumer.ImplementationType == typeof(LogContextMiddleware)); var authExclusions = new List<Type> { typeof(StatusController), typeof(PruebaSinAuthController) }; container.RegisterConditional( typeof(IEnumerable<Type>), _ => InstanceProducer.ForInstance(authExclusions), c => c.Consumer.ImplementationType == typeof(AuthorizationMiddleware<AppToken>)); // 注册中间件 container.Register<LogContextMiddleware>(Lifestyle.Transient); container.Register<AuthorizationMiddleware<AppToken>>(Lifestyle.Transient);
内容的提问来源于stack exchange,提问作者Iñaki P. B.
相关产品推荐
相关产品推荐

