Что определенно не так, когда Transient вводится в синглтон? - PullRequest
1 голос
/ 24 мая 2019

Существует проблема неправильно сконфигурированных DI-контейнеров с именем Captive Dependency от Mark Seemann. Это, например, очевидно, когда зависимость "PerCall" вводится в "синглтон". Но как насчет сценария, когда "переходный процесс" вводится в "синглтон"? Для меня не так очевидно, почему я не должен делать это, особенно для некоторых сценариев, таких как таймер, зарегистрированный как переходный процесс, внедренный в одноэлементную службу и живущий там навсегда.

В контейнере SimpleInjector DI есть Lifestyle Mismatches диагностическое предупреждение . В описании сказано:

для переходного компонента безопасно зависеть от одноэлементного, но не наоборот

Почему это плохо? Хороший пример плохих вещей в этом случае будет чрезвычайно полезным. Есть ли какое-либо ограничение, когда это «всегда» плохо или могут быть разрешены некоторые сценарии (см. Мой пример выше)?

Ответы [ 2 ]

4 голосов
/ 24 мая 2019

Это зависит от вашего определения того, что на самом деле означает «Переходный процесс».

Простой Инжектор считает, что временные регистрации продолжаются только в течение короткого времени; временный , то есть недолговечный и не использованный повторно. По этой причине Simple Injector предотвращает попадание компонентов Transient в потребителей Scoped и Singleton, так как ожидается, что они прослужат дольше, что в противном случае могло бы привести к несоответствию образа жизни. ( источник )

Некоторые другие DI-контейнеры используют другое определение для «Transient». Например, .NET Core DI Container (MS.DI) рекомендует, чтобы ваши временные регистрации были « облегченными службами без сохранения состояния. » Поскольку предполагается, что они не сохраняют состояние, безопасно вводить их в потребителей любым другое время жизни, пока у них нет собственных зависимостей (под). «С учетом состояния» в контексте MS.DI обычно означает ограниченную зависимость. Определение переходного процесса в MS.DI идентично тому, что Autofac называет Instance Per Dependency . IMO, наименование Autofac является более правильным, потому что концептуально существует большая разница между двумя определениями переходного процесса, и я полагаю, что большинство DI-контейнеров следуют «, действующему только в течение короткого времени; временное » определение.

Пока ваш временный компонент не имеет состояния , и пока этот компонент не содержит зависимостей с состоянием, нет никакого вреда для внедрения его в одноэлементный (или ограниченный) потребитель. Впрочем, введение такого компонента без сохранения состояния в синглтон все еще делает этот компонент долгоживущим , что является чем-то совершенно иным, чем недолговечным . Поскольку Simple Injector не знает, содержит ли ваш компонент состояние, он считает все переходные процессы недолговечными и поэтому предупреждает вас о введении переходных процессов в синглтоны.

3 голосов
/ 24 мая 2019

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

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

Если вы регистрируете класс как одноэлементный, вы рассматриваете его как потокобезопасный, потому что вы можете использовать один и тот же экземпляр одновременно в нескольких потоках.Если вы регистрируете класс как переходный, скорее всего, это легкий и не поточно-ориентированный класс.Вот почему вы зарегистрировали его как переходный, а не синглтон, верно?И именно поэтому вы видите предупреждения: небезопасно использовать временные объекты одновременно.Во встроенном IoC ядра asp.net в этом случае вы столкнетесь с исключением времени выполнения.

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

...