如何为ViewModel实现依赖注入?Unity MVC项目构造注入正确性咨询
嗨,我来帮你梳理下这个问题~
首先,你现在通过控制器构造函数注入依赖,再传递给ViewModel构造函数来实例化的方式,本身是正确的——它符合依赖注入的核心思想:依赖项由外部提供,而非内部自行创建,这样能实现代码解耦,也方便后续做单元测试。
不过这种方式存在一些可以优化的地方,长期维护下来可能会有麻烦:
- 你的控制器已经注入了一堆Business接口,随着业务扩展,如果ViewModel的依赖增加,或者需要实例化多个ViewModel,控制器的构造函数会变得越来越臃肿,代码可读性和维护性都会下降。
- 控制器需要明确知道ViewModel的所有依赖细节,这其实违背了依赖倒置原则的部分设计初衷——控制器本该只负责ViewModel的使用,而非它的依赖构建。
更优雅的解决方案:让Unity直接注入ViewModel
其实可以让Unity容器直接负责ViewModel的依赖解析,不需要控制器做中转,步骤如下:
在Unity中注册ViewModel
把你的ViewModel类型注册到Unity容器里,比如假设你有个PersonnelViewModel:container.RegisterType<PersonnelViewModel>();Unity会自动识别ViewModel构造函数中的依赖(也就是那些
IPersonnelAMBusiness之类的接口),并帮你完成注入,前提是这些依赖已经在容器中注册过。控制器直接注入ViewModel
改造控制器的构造函数,直接注入ViewModel而非一堆Business接口:private readonly PersonnelViewModel _personnelViewModel; public YourController(PersonnelViewModel personnelViewModel) { _personnelViewModel = personnelViewModel; }这样控制器的构造函数会清爽很多,也不需要手动传递依赖给ViewModel。
动态创建ViewModel的场景
如果需要根据不同场景动态创建ViewModel实例,可以使用Unity的工厂模式,比如注册一个ViewModel工厂,在控制器中注入工厂,再通过工厂创建实例,避免控制器直接依赖ViewModel的构造细节。
另外补充:如果ViewModel需要访问请求上下文(比如当前用户信息),可以在ViewModel的构造函数中注入HttpContextBase,同时给ViewModel设置PerRequestLifetimeManager,确保每个请求对应一个独立的ViewModel实例:
container.RegisterType<PersonnelViewModel>(new PerRequestLifetimeManager());
总的来说,你当前的实现是正确的,但通过Unity直接注入ViewModel的方式会更符合DI的最佳实践,也能让代码结构更清晰。
内容的提问来源于stack exchange,提问作者clement

