C# 为什么Ninject不使用InCallScope释放已处置的对象?
我正试图在WinForms应用程序中使用Ninject(版本3.0.1),我有几个(当前)自绑定服务类,我使用Ninject构建它们。某些服务类需要其他服务类(子服务)。大多数服务类都需要一个存储库来与数据库交互,因为我有一个抽象的IRepository接口。我需要为服务类中的整个服务层次结构拥有相同的存储库,因此在绑定IRepository时使用C# 为什么Ninject不使用InCallScope释放已处置的对象?,c#,.net-4.0,ninject,ninject-extensions,C#,.net 4.0,Ninject,Ninject Extensions,我正试图在WinForms应用程序中使用Ninject(版本3.0.1),我有几个(当前)自绑定服务类,我使用Ninject构建它们。某些服务类需要其他服务类(子服务)。大多数服务类都需要一个存储库来与数据库交互,因为我有一个抽象的IRepository接口。我需要为服务类中的整个服务层次结构拥有相同的存储库,因此在绑定IRepository时使用InCallScope()范围。目前我使用XPO作为ORM工具,所以我有一个XpoRepository实现,我将绑定到它。有关此场景,请参阅我的 我的
InCallScope()
范围。目前我使用XPO作为ORM工具,所以我有一个XpoRepository实现,我将绑定到它。有关此场景,请参阅我的
我的装订看起来像这样:
Bind<IRepository>().To<XpoRepository>().InCallScope();
while (true) {
if (CancellatioPending())
break;
using (var service = _kernel.Get<Service1>())
{
// do some stuff using the service class
}
Thread.Sleep(20*1000);
}
我在后台线程(使用TPL)中使用其中一个服务,循环如下:
Bind<IRepository>().To<XpoRepository>().InCallScope();
while (true) {
if (CancellatioPending())
break;
using (var service = _kernel.Get<Service1>())
{
// do some stuff using the service class
}
Thread.Sleep(20*1000);
}
while(true){
if(cancellationding())
打破
使用(var服务=_kernel.Get())
{
//使用服务类做一些事情
}
线程。睡眠(20*1000);
}
在使用Ninject之前,我有相同的结构,所以我(我认为)正确地实现了对每个对象的处理,包括在正确位置的存储库。然而,我注意到,由于我使用Ninject来实现这一点,我的应用程序中有一个很大的内存泄漏,它每2-3小时就会崩溃一次,OutOfMemoryException。我在循环中放置了一个断点,并注意到Ninject缓存有数千个条目,其中充满了已处理的XpoRepository对象。我猜它们是由我处理的,但我不确定是谁调用了dispose方法
为什么Ninject会持有这些处置过的对象?我希望当我在using块的末尾处理主服务时(由于InCallScope(),这是IRepository对象的作用域),其作用域中的每个对象都应该由Ninject处理和释放
编辑:在任何关于为什么这种模式不好的评论或回答之前,我知道它可能会更好。我知道我可以提取服务接口来实际使用DI并提高可测试性,我还知道我可能应该使用
Func
作为构造函数参数,并将其注入其中,就像每个服务都可以有自己的责任来处理存储库一样。只是我目前没有时间进行这样的重构。Ninject将发布存储库,前提是以下所有内容都是正确的:
- 没有人持有对服务1的引用
- service1本身是GC'd(因为您有20秒的线程睡眠时间,所以很有可能它已升级到gen2,并且很少发布)
- 缓存修剪是在service1被GC’d之后执行的,缓存修剪间隔默认为30秒。您可能需要尝试更短的间隔时间
- 与上一点不同,您可以尝试通过在service1中实现
来强制立即发布Ninject.Infrastructure.dispose.INotifyWhenDisposed