Управление прототипами, с другой стороны, является полностью ответственностью вызывающего кода.

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

Вопрос в основном:

Как вы относитесь к конкретным типам по отношению к контейнерам IoC? В частности, кто отвечает за их удаление, если они требуют утилизации, и как эти знания распространяются на вызывающий код?

Вы требуете, чтобы они были IDisposable? Если нет, то является ли этот код перспективным, или вы не можете использовать одноразовые предметы? Если вы применяете требования IDisposable к интерфейсам и конкретным типам, чтобы быть ориентированными на будущее, кто несет ответственность за объекты, внедренные как часть вызовов конструктора?

редактировать: Я принял ответ@ Крис Баллард так как это самый близкий к подходу, с которым мы закончили.

По сути, мы всегда возвращаем тип, который выглядит следующим образом:

public interface IService<T> : IDisposable
    where T: class
{
    T Instance { get; }
    Boolean Success { get; }
    String FailureMessage { get; } // in case Success=false
}

Затем мы возвращаем объект, реализующий этот интерфейс, как из .Resolve, так и .TryResolve, так что то, что мы получаем в вызывающем коде, всегда имеет один и тот же тип.

Теперь объект, реализующий этот интерфейс,IService<T> IDisposable, и долженвсегда утилизировать. Это не зависит от программиста, который разрешает службу, чтобы решить, является лиIService<T> объект должен быть утилизирован или нет.

Тем не менее, и это важная часть, должен ли экземпляр службы располагаться или нет, что знания запекаются в объекте, реализующемIService<T>, так что если это сервис с фабричной областью (т. е. каждый вызов Resolve заканчивается новым экземпляром службы), то экземпляр службы будет удален, когдаIService<T> объект расположен.

Это также позволило поддерживать другие специальные области, такие как пул. Теперь мы можем сказать, что нам нужно минимум 2 экземпляра службы, максимум 15 и обычно 5, что означает, что каждый вызов .Resolve будет либо извлекать экземпляр службы из пула доступных объектов, либо создавать новый. А потом, когдаIService<T> объект, содержащий службу в пуле, удаляется, экземпляр службы освобождается обратно в пул.

Конечно, это заставило весь код выглядеть так:

using (var service = ServiceContainer.Global.Resolve<ISomeService>())
{
    service.Instance.DoSomething();
}

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

Исходный вопрос следует для потомков

Длинный вопрос приходит сюда:

У нас есть контейнер IoC, который мы используем, и недавно мы обнаружили, что является проблемой.

В коде, отличном от IoC, когда мы хотели использовать, скажем, файл, мы использовали такой класс:

using (Stream stream = new FileStream(...))
{
    ...
}

Не было никаких сомнений относительно того, является ли этот класс чем-то, что содержит ограниченный ресурс, или нет, так как мы знали, что файлы должны быть закрыты, и сам класс реализовал IDisposable. Правило состоит в том, что каждый класс, из которого мы создаем объект, реализующий IDisposable, должен быть удален. Никаких вопросов не было задано. Пользователь этого класса не должен решать, является ли вызов Dispose необязательным или нет.

Итак, перейдем к первому шагу в направлении контейнера IoC. Давайте предположим, что мы не хотим, чтобы код говорил напрямую с файлом, а вместо этого пройдем один уровень косвенности. Давайте назовем этот класс BinaryDataProvider для этого примера. Внутри класс использует поток, который все еще является одноразовым объектом, поэтому приведенный выше код будет изменен на:

using (BinaryDataProvider provider = new BinaryDataProvider(...))
{
    ...
}

Это мало что меняет. Знание того, что класс реализует IDisposable, все еще здесь, без вопросов, нам нужно вызвать Dispose.

Но давайте предположим, что у нас есть классы, которые предоставляют данные, которые сейчас не используют такие ограниченные ресурсы.

Приведенный выше код может быть записан как:

BinaryDataProvider provider = new BinaryDataProvider();
...

Хорошо, пока все хорошо, но здесь идет главный вопрос. Давайте предположим, что мы хотим использовать контейнер IoC для внедрения этого провайдера вместо зависимости от конкретного конкретного типа.

Код будет тогда:

IBinaryDataProvider provider =
    ServiceContainer.Global.Resolve<IBinaryDataProvider>();
...

Обратите внимание, что я предполагаю, что существует независимый интерфейс, через который мы можем получить доступ к объекту.

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

Как мы видим, мы должны выбрать одно решение:

Реализуйте проверку во время выполнения, которая проверяет, что если конкретный тип, который регистрируется, реализует IDisposable, требует, чтобы интерфейс, через который он предоставляется, также реализовывал IDisposable. Это не хорошее решениеПрежде чем накладывать ограничения на используемые интерфейсы, они всегда должны наследоваться от IDisposable, чтобы быть ориентированными на будущееОбеспечить выполнение, чтобы никакие конкретные типы не могли быть IDisposable, так как это определенно не обрабатывается кодом, использующим контейнер IoCПросто оставьте это на усмотрение программиста, чтобы проверить, реализует ли объект IDisposable и «делать правильные вещи»?Есть ли другие?

Кроме того, как насчет внедрения объектов в конструкторы? Наш контейнер и некоторые другие контейнеры, которые мы рассмотрели, способны вводить свежий объект в параметр в конструктор конкретного типа. Например, если нашBinaryDataProvider нужен объект, который реализуетILogging интерфейс, если мы применяем IDispose- «способность» к этим объектам, кто несет ответственность за удаление объекта регистрации?

Как вы думаете? Я хочу мнения, хорошие и плохие.

Ответы на вопрос(3)

Ваш ответ на вопрос