Рекомендовалось мне, чтобы при использовании контейнера МОК я изменил это:
class Foobar: IFoobar, IDisposable {};
В это:
interface IFoobar: IDisposable{};
class Foobar : IFoobar{};
Я задаюсь вопросом, ли это в порядке, или если это решает одну проблему и создает другого. Это, конечно, решает проблему, где я плохо хочу сделать это:
using( IFoobar = myContainer.Resolve<IFoobar>() )
{ ... }
И теперь я знаю, что любая замена не вызовет ошибку времени выполнения.
С другой стороны, теперь все мои фиктивные объекты должны обработать IDisposable также. Действительно ли я прав, что большая часть любой платформы насмешки обрабатывает это легко? Если да, то, возможно, это - надуманный вопрос.
Или это? Там другой - скрытый глюк, за которым я должен наблюдать? Мне, конечно, приходит в голову, что, если я использовал контейнер МОК не для модульных тестов / насмешка, а для истинной сервисной независимости, затем это могло бы быть проблемой, потому что, возможно, только один из моих выгружаемых сервисов на самом деле имеет дело с неуправляемыми ресурсами (и теперь я должен реализовать пустые операции "IDispose" в этих других сервисах).
Даже эта последняя проблема, я предполагаю, что мог жить с ради получения способности использовать оператор "использования", поскольку я продемонстрировал выше. Но я следую популярной конвенции, или я пропускаю совершенно другое и лучшее решение?
Создание интерфейса от IDisposable, на мой взгляд, является запахом дизайна, который указывает на Leaky Abstraction . Как выразился Николас Блюмхардт :
интерфейс [...] обычно не должен быть одноразовым. У того, кто определяет интерфейс, нет возможности предвидеть все возможные его реализации - вы всегда можете придумать одноразовую реализацию практически любого интерфейса.
Подумайте, почему вы хотите добавить IDisposable в свой интерфейс. Вероятно, это потому, что вы имеете в виду конкретную реализацию . Следовательно, реализация просачивается в абстракцию.
Ценный контейнер DI должен знать, когда он создает экземпляр одноразового типа. Когда вы впоследствии попросите контейнер освободить граф объектов, он должен автоматически удалить одноразовые компоненты (если их время истекло в соответствии с их образом жизни).
Я знаю, что по крайней мере Castle Windsor и Autofac делают это.
Так что в вашем случае вы должны сохранить свой типаж следующим образом:
class Foobar: IFoobar, IDisposable {};
Вы можете найти сообщение Николаса Блюмхардта The Relationship Zoo также интересным - особенно обсуждение о Owned
.