Я пытаюсь использовать Ninject (версия 3.0.1) в приложении WinForms, у меня есть несколько (в настоящее время) self-binded класс сервиса, который я создаю с использованием Ninject. Для некоторых классов обслуживания нужны другие классы обслуживания (под-сервисы). Для большинства этих классов обслуживания необходим репозиторий для взаимодействия с базой данных, для чего у меня есть абстрактный интерфейс IRepository. Мне нужно иметь один и тот же репозиторий для всей служебной иерархии в классе службы, поэтому я использую область InCallScope()
при привязке IRepository. В настоящее время я использую XPO как инструмент ORM, поэтому у меня есть реализация XpoRepository, с которой я связываюсь. См. Мой other question об этом сценарии.Почему Ninject не выпускает удаленные объекты с помощью InCallScope?
Мои привязки выглядит следующим образом:
Bind<IRepository>().To<XpoRepository>().InCallScope();
У меня нет явных ToSelf()
привязки для каждого класса обслуживания, поэтому я предполагаю, когда я получаю их от Ninject, они должны иметь переходные рамки, которые я истолковать так как я должен их вручную уничтожить.
Предположим, что у меня есть сервисный класс Services1 и Service2, оба имеют параметр конструктора типа 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. Я полагаю, что они настроены мной, но я не уверен, кто вызвал метод dispose.
Почему Ninject держит эти расположенные объекты? Я ожидал бы, что когда я удалю главную службу в конце блока использования (который является областью объектов IRepository из-за InCallScope()), каждый объект в его области должен быть удален и выпущен Ninject.
EDIT: Перед любыми комментариями или ответами о том, почему этот шаблон не является хорошим, я знаю, что это может быть лучше. Я знаю, что я мог бы извлечь служебные интерфейсы, чтобы на самом деле использовать DI и улучшить тестируемость, и я также знаю, что я должен, вероятно, использовать Func<IRepository>
в качестве параметра конструктора и вводить в него, и, как будто каждый сервис может иметь свою собственную ответственность за распоряжение репозиторий. Просто у меня нет времени для таких рефакторингов в настоящее время.
смотри также http://stackoverflow.com/questions/15599325/looking-for-a-ninject-scope-that -behaves-like-inrequestscope –