基于Prism6的WPF应用中Unity容器何时处置注入对象?
关于Prism 6 + Unity下依赖对象的处置时机梳理
我之前在做Prism 6 + Unity的WPF项目时,也纠结过UoW、DbContext这类对象的Dispose时机问题,结合实践给你拆解下关键逻辑:
1. 先明确Unity的生命周期配置
你在注册依赖时,有没有指定生命周期管理器?这直接决定了对象的存活时长:
- TransientLifetimeManager:每次解析都创建新实例,容器不会持有引用,这类对象的Dispose需要你手动触发(比如在ViewModel的Dispose里调用)。
- ContainerControlledLifetimeManager(单例):整个应用生命周期只有一个实例,只有当Unity容器被Dispose时,才会触发它的Dispose方法。
- PerResolveLifetimeManager:每次解析请求创建一个实例,适合UoW这种和单次业务请求绑定的场景。
一般来说,DbContext和UoW不建议注册为单例——因为DbContext是有状态的,长期持有会导致缓存膨胀、并发问题,更合理的是和ViewModel同生命周期。
2. Prism ViewModel的Dispose触发时机
如果你的ViewModel实现了IDisposable接口,Prism会在View被销毁时自动调用它的Dispose方法:
- 对于窗口类View:当窗口关闭(不是最小化)时,View会被销毁,ViewModel的Dispose会触发。
- 对于导航页View:当你导航离开该页面,且没有设置
KeepAlive="True"时,View会被销毁,ViewModel的Dispose也会触发。
这就是为什么你应该把UoW、DbContext的Dispose逻辑绑定到ViewModel的Dispose上——ViewModel的生命周期和用户交互的页面/窗口绑定,能确保资源在合适的时机被释放。
3. 正确的Dispose实现示例
ViewModel中的Dispose
public class OrderViewModel : BindableBase, IDisposable { private readonly IOrderUnitOfWork _orderUow; private bool _disposed = false; public OrderViewModel(IOrderUnitOfWork orderUow) { _orderUow = orderUow; } // 这里写业务逻辑... protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // 手动触发UoW的Dispose,进而释放DbContext _orderUow.Dispose(); } _disposed = true; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } }
工作单元(UoW)的Dispose
public class OrderUnitOfWork : IOrderUnitOfWork, IDisposable { private readonly AppDbContext _dbContext; private bool _disposed = false; public OrderUnitOfWork(AppDbContext dbContext) { _dbContext = dbContext; } // UoW的业务方法:比如SaveChanges()... protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { // 释放DbContext _dbContext.Dispose(); } _disposed = true; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } }
4. 为什么你的断点没触发?
可能的几个原因:
- 对象生命周期没到:比如ViewModel是单例,或者View设置了
KeepAlive="True",导致View/ViewModel没被销毁,Dispose自然不会触发。 - Unity容器没被Dispose:如果是单例对象,只有当Prism应用关闭时,PrismApplication才会自动Dispose Unity容器,这时候单例对象的Dispose才会执行。
- 没手动触发Dispose:如果是Transient对象,容器不会帮你管理Dispose,必须在持有它的对象(比如ViewModel)的Dispose里手动调用。
5. 注册依赖时的建议
在Prism的RegisterTypes方法里,给UoW和DbContext配置合适的生命周期:
protected override void RegisterTypes(IContainerRegistry containerRegistry) { // 用PerResolve或者Transient,确保每次ViewModel获取的都是新实例 containerRegistry.Register<IOrderUnitOfWork, OrderUnitOfWork>(new PerResolveLifetimeManager()); containerRegistry.Register<AppDbContext>(new PerResolveLifetimeManager()); }
这样每次解析ViewModel时,都会创建新的UoW和DbContext实例,当ViewModel被销毁时,通过它的Dispose就能链式释放这些资源。
内容的提问来源于stack exchange,提问作者Junior
相关产品推荐
相关产品推荐

