Контейнеры МОК и IDisposable

Рекомендовалось мне, чтобы при использовании контейнера МОК я изменил это:

class Foobar: IFoobar, IDisposable {};

В это:

interface IFoobar: IDisposable{};
class Foobar : IFoobar{};

Я задаюсь вопросом, ли это в порядке, или если это решает одну проблему и создает другого. Это, конечно, решает проблему, где я плохо хочу сделать это:

using( IFoobar = myContainer.Resolve<IFoobar>() )
{ ... }

И теперь я знаю, что любая замена не вызовет ошибку времени выполнения.

С другой стороны, теперь все мои фиктивные объекты должны обработать IDisposable также. Действительно ли я прав, что большая часть любой платформы насмешки обрабатывает это легко? Если да, то, возможно, это - надуманный вопрос.

Или это? Там другой - скрытый глюк, за которым я должен наблюдать? Мне, конечно, приходит в голову, что, если я использовал контейнер МОК не для модульных тестов / насмешка, а для истинной сервисной независимости, затем это могло бы быть проблемой, потому что, возможно, только один из моих выгружаемых сервисов на самом деле имеет дело с неуправляемыми ресурсами (и теперь я должен реализовать пустые операции "IDispose" в этих других сервисах).

Даже эта последняя проблема, я предполагаю, что мог жить с ради получения способности использовать оператор "использования", поскольку я продемонстрировал выше. Но я следую популярной конвенции, или я пропускаю совершенно другое и лучшее решение?

9
задан Mark Seemann 14 April 2010 в 07:55
поделиться

1 ответ

Создание интерфейса от IDisposable, на мой взгляд, является запахом дизайна, который указывает на Leaky Abstraction . Как выразился Николас Блюмхардт :

интерфейс [...] обычно не должен быть одноразовым. У того, кто определяет интерфейс, нет возможности предвидеть все возможные его реализации - вы всегда можете придумать одноразовую реализацию практически любого интерфейса.

Подумайте, почему вы хотите добавить IDisposable в свой интерфейс. Вероятно, это потому, что вы имеете в виду конкретную реализацию . Следовательно, реализация просачивается в абстракцию.

Ценный контейнер DI должен знать, когда он создает экземпляр одноразового типа. Когда вы впоследствии попросите контейнер освободить граф объектов, он должен автоматически удалить одноразовые компоненты (если их время истекло в соответствии с их образом жизни).

Я знаю, что по крайней мере Castle Windsor и Autofac делают это.

Так что в вашем случае вы должны сохранить свой типаж следующим образом:

class Foobar: IFoobar, IDisposable {};

Вы можете найти сообщение Николаса Блюмхардта The Relationship Zoo также интересным - особенно обсуждение о Owned .

11
ответ дан 4 December 2019 в 20:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: