PaymentManager构造函数依赖未注册及容器配置无效问题求助
问题解答:DI容器注册集合后构造函数参数报错的问题
嘿,我来帮你搞定这个「配置无效」的问题!
首先直接给你结论:没错,这个报错大概率就是因为构造函数的参数类型是List<IPaymentMethod>,而你注册集合后,DI容器默认只能提供IEnumerable<IPaymentMethod>类型的实例导致的。大部分主流DI容器(比如你用的看起来像是Autofac)在调用RegisterCollection<T>后,会自动注册IEnumerable<T>来返回所有已注册的实现,但不会自动处理List<T>这种具体集合类型的注入请求,所以容器找不到匹配的注册项,就会抛出配置无效的错误。
接下来给你两种解决方案,按需选择:
方案一:修改构造函数参数为IEnumerable<IPaymentMethod>(推荐)
这是最符合依赖倒置原则的做法,我们应该依赖抽象而不是具体实现。你的代码如果只是需要遍历支付方式,IEnumerable<T>完全够用,而且DI容器对它的支持是原生的,不需要额外配置。
修改后的构造函数示例:
public class PaymentManager { private readonly IEnumerable<IPaymentMethod> _paymentMethods; // 把参数类型改成IEnumerable<IPaymentMethod> public PaymentManager(IEnumerable<IPaymentMethod> paymentMethods) { _paymentMethods = paymentMethods ?? throw new ArgumentNullException(nameof(paymentMethods)); } // 后续业务逻辑里,直接遍历_paymentMethods即可 }
修改完之后,你之前的RegisterCollection代码不需要做任何改动,容器会自动把所有注册的IPaymentMethod实现注入到构造函数里。
方案二:保留List<IPaymentMethod>参数,手动配置转换
如果你因为某些原因必须使用List<IPaymentMethod>作为参数,那需要告诉DI容器如何将已注册的IEnumerable<IPaymentMethod>转换成List<T>。以Autofac为例,有两种方式:
方式1:注册PaymentManager时指定参数转换
// 先注册你的支付方式集合 container.RegisterCollection<IPaymentMethod>(new[] { typeof(AuthorizeNetProvider), typeof(StripeProvider), typeof(PayPalProProvider), typeof(PayPalStandardProvider), typeof(IntuitProvider), typeof(UsaEpayProvider), typeof(ITransactProvider), typeof(SecureNetProvider), typeof(ExposurePayProvider), typeof(PayTraceProvider), typeof(BraintreeProvider) }); // 注册PaymentManager时,手动处理List参数 container.RegisterType<PaymentManager>() .WithParameter( // 匹配List<IPaymentMethod>类型的参数 (parameter, context) => parameter.ParameterType == typeof(List<IPaymentMethod>), // 把IEnumerable转换为List (parameter, context) => context.Resolve<IEnumerable<IPaymentMethod>>().ToList() );
方式2:单独注册List<IPaymentMethod>类型
// 先注册集合 container.RegisterCollection<IPaymentMethod>(new[] { /* 你的实现类型数组 */ }); // 注册List<IPaymentMethod>,基于已有的IEnumerable实现 container.Register(c => c.Resolve<IEnumerable<IPaymentMethod>>().ToList()) .As<List<IPaymentMethod>>(); // 之后正常注册PaymentManager即可,容器会自动找到List<IPaymentMethod>的注册 container.RegisterType<PaymentManager>();
最后再啰嗦一句:优先选方案一哦,它不仅能解决当前问题,还能让你的代码更符合面向对象设计原则,降低耦合度。
内容的提问来源于stack exchange,提问作者Mike Flynn
相关产品推荐
相关产品推荐

