我正在尝试在WinForms应用程序中使用Ninject(版本3.0.1),我有几个(当前)自绑定服务类,我使用Ninject构建。某些服务类需要其他服务类(子服务)。大多数这些服务类都需要一个存储库来与数据库进行交互,因为我有一个抽象的IRepository接口。我需要为服务类中的整个服务层次结构提供相同的存储库,因此在绑定IRepository时我使用InCallScope()
作用域。目前我正在使用XPO作为ORM工具,所以我有一个XpoRepository实现,我绑定到它。有关此方案,请参阅我的other question。
我的绑定看起来像这样:
Bind<IRepository>().To<XpoRepository>().InCallScope();
我没有为每个服务类提供明确的ToSelf()
绑定,所以我假设当我从Ninject获取它们时,它们应该具有瞬态范围,我将其解释为必须手动处理它们。
假设我有一个Services1和一个Services2服务类,它们都具有IRepository类型的构造函数参数。现在假设Services1想要使用Services2的某些方法,所以我将另一个构造函数参数添加到Services1,类型为Services2。没有Ninject,我会这样做:
var repo = new MyRepository(); // implementing IRepository
var service1 = new Services1(repo, new Services2(repo));
我正在使用后台线程中的一个服务(使用TPL),在这样的循环中:
while (true) {
if (CancellatioPending())
break;
using (var service = _kernel.Get<Service1>())
{
// do some stuff using the service class
}
Thread.Sleep(20*1000);
}
在使用Ninject之前我有相同的结构,所以我(我认为)正确实现了对每个对象的处理,包括正确位置的存储库。但是,我注意到,因为我正在使用Ninject,我的应用程序中存在大量内存泄漏,并且每隔2-3小时就会出现OutOfMemoryException崩溃。我在循环中放置了一个断点,并注意到Ninject缓存有数千个条目,其中包含已放置的XpoRepository对象。我想,它们是由我处置的,但我不确定是谁调用了处理方法。
为什么Ninject持有这些被处置的物品?我希望当我将主服务部署在using块的末尾时(由于InCallScope()而导致IRepository对象的范围),其范围内的每个对象都应由Ninject处理和释放。
编辑:在对这种模式不好的任何评论或回答之前,我知道它可能会更好。我知道我可以提取服务接口以实际使用DI并提高可测试性,我也知道我应该使用Func<IRepository>
作为构造函数参数,并注入其中,并且每个服务都可以拥有它拥有处理存储库的可靠性。我现在没有时间进行这样的重构。
答案 0 :(得分:4)
如果满足以下所有条件,Ninject将发布存储库:
Ninject.Infrastructure.Disposal.INotifyWhenDisposed
来强制立即发布