为何Unity调用无参数构造函数?TopMenuViewModel依赖注入失败
解决Unity未调用标注[InjectionConstructor]构造函数的问题
我之前在使用Unity做依赖注入时也踩过这个一模一样的坑,给你几个实用的排查和解决方向:
1. 先检查所有依赖接口是否已注册到Unity容器
Unity只会解析已经在容器中注册过的依赖类型,如果你的IPersonnelAMBusiness、IDocumentBusiness或者IMessageBusiness有任何一个没完成注册,Unity会直接放弃调用带参构造,转而使用无参构造函数。
你需要确保容器初始化时完成所有依赖的注册,比如:
var container = new UnityContainer(); // 为每个接口绑定对应的实现类 container.RegisterType<IPersonnelAMBusiness, PersonnelAMBusiness>(); container.RegisterType<IDocumentBusiness, DocumentBusiness>(); container.RegisterType<IMessageBusiness, MessageBusiness>();
2. 确认[InjectionConstructor]特性的命名空间正确
这个特性属于Microsoft.Practices.Unity命名空间,别不小心引用了其他IoC库的同名特性——不同框架的特性Unity是不识别的,一定要在ViewModel文件顶部加上:
using Microsoft.Practices.Unity;
3. 绝对不要手动new ViewModel实例
如果你是通过var vm = new TopMenuViewModel()这种方式创建实例,Unity完全没有机会介入注入过程。必须通过Unity容器来解析ViewModel:
var viewModel = container.Resolve<TopMenuViewModel>();
如果是在WPF/Prism这类MVVM框架中使用,要确保ViewModel是通过ViewModelLocator或者容器注入的方式获取,而不是手动实例化。
4. 确保只有一个构造函数标注了[InjectionConstructor]
如果不小心给多个构造函数都加了这个特性,Unity会陷入选择困境,大概率会 fallback 到无参构造。检查你的代码,确保只有需要注入的那个带参构造有这个标注。
5. 开启Unity诊断日志排查隐藏问题
如果以上步骤都没问题,可以开启Unity的诊断日志,查看解析过程中是否有隐藏的错误(比如某个依赖的实例化失败)。你可以通过以下方式开启日志:
container.AddExtension(new Diagnostic());
日志会输出详细的解析流程,帮你快速定位问题所在。
完整的正确示例代码
using Microsoft.Practices.Unity; public class TopMenuViewModel { public int unreadMessagesCount { get; set; } public PersonnelAMEntity personnel { get; set; } public IList<DocumentTypeEntity> quickDocumentTypes { get; set; } private readonly IPersonnelAMBusiness _personnelAMBusinessRepo; private readonly IDocumentBusiness _documentBusinessRepo; private readonly IMessageBusiness _messageBusinessRepo; // 标注为注入构造函数 [InjectionConstructor] public TopMenuViewModel(IPersonnelAMBusiness personnelRepo, IDocumentBusiness documentRepo, IMessageBusiness messageRepo) { _personnelAMBusinessRepo = personnelRepo; _documentBusinessRepo = documentRepo; _messageBusinessRepo = messageRepo; // 这里可以初始化依赖相关的业务逻辑 } // 无参构造函数(仅作为 fallback 场景使用) public TopMenuViewModel() { } } // 容器注册与解析示例 var container = new UnityContainer(); container.RegisterType<IPersonnelAMBusiness, PersonnelAMBusiness>(); container.RegisterType<IDocumentBusiness, DocumentBusiness>(); container.RegisterType<IMessageBusiness, MessageBusiness>(); // 通过容器解析,此时会调用带参构造函数 var viewModel = container.Resolve<TopMenuViewModel>();
内容的提问来源于stack exchange,提问作者clement
相关产品推荐
相关产品推荐

