WPF示例应用中,ItemViewModel实例化应手动还是交由DI容器处理?
既然你已经熟悉MVVM和DI,咱们直接聊核心——这两种方式都有适用场景,没有绝对的「正确答案」,得看你的ItemViewModel实际情况:
手动实例化完全合适的场景
如果你的ItemViewModel没有任何需要注入的依赖项,创建它只需要传入从业务模型(比如Item实体)来的简单数据(ID、名称、状态这些),那直接手动new完全没问题。毕竟你也提到它特性非常具体、没有可抽象的内容,这种情况下用DI反而属于过度设计——平白增加了容器注册的工作量,还让代码变得绕了一圈。
举个直观的例子,你从数据库拿到List<Item>后,直接遍历创建集合:
Items = new ObservableCollection<ItemViewModel>( items.Select(item => new ItemViewModel(item.Id, item.Title, item.IsCompleted)) );
这种写法直接清晰,维护起来也简单,完全符合MVVM的设计要求。
适合委托给DI容器的场景
但如果ItemViewModel需要依赖其他服务(比如ILogger、IItemDetailService这类需要注入的组件),那交给DI容器来创建就更合理了。这时候你可以通过注册一个工厂委托来简化操作:
- 先在DI容器里注册
ItemViewModel类型,再注册对应的工厂(以Microsoft.Extensions.DependencyInjection为例):
services.AddTransient<ItemViewModel>(); services.AddSingleton<Func<Item, ItemViewModel>>(sp => item => new ItemViewModel(item.Id, item.Title, sp.GetRequiredService<ILogger<ItemViewModel>>()) );
- 然后在
MainViewModel里注入这个工厂,用它来创建实例:
private readonly Func<Item, ItemViewModel> _itemVmFactory; public MainViewModel(Func<Item, ItemViewModel> itemVmFactory) { _itemVmFactory = itemVmFactory; // 从数据源获取items后 Items = new ObservableCollection<ItemViewModel>(items.Select(_itemVmFactory)); }
这样做的好处是,MainViewModel不用关心ItemViewModel的依赖细节,完全符合依赖倒置原则;而且如果以后ItemViewModel加新的依赖,只需要修改工厂注册的代码,不用动MainViewModel的逻辑。
额外考虑:未来扩展性
哪怕现在ItemViewModel没有依赖,如果你预判未来可能会给它加一些服务依赖(比如要加编辑功能需要调用API服务),那提前用DI工厂的方式实现,后期改动会更小。但如果确定它永远只会是一个纯展示型的ViewModel,只依赖业务模型的数据,那手动实例化就是最简洁的选择。
总结下来:根据ItemViewModel的依赖情况和未来规划选就行,不用为了「符合DI规范」而强行用容器,实用优先。
内容的提问来源于stack exchange,提问作者Nikhil Vartak

