При инъекции зависимостей Кодина я не хочу распространять экземпляры кодеина повсюду

Используя Kodein, я нахожу, что мне нужно передавать экземпляры kodein или вводить их в модули и классы. Но иногда у меня есть классы, которые так отключены. Я хочу, чтобы они просто могли обнаружить «один истинный Кодин». Поскольку это приложение на стороне сервера, и у меня есть только одна область Kodein, это должно быть легко. Я могу создать глобальный объект, например:

val kodeinGlobal: Kodein = Kodein { ... } 

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

Может ли Kodein найти основную, верхнюю или глобальную область действия самостоятельно?

Примечание: этот вопрос намеренно написан автором и отвечает на него ( Self-Answered Questions ), так что идиоматические ответы на часто задаваемые темы Kotlin / Kodein присутствуют в SO.

В Kodein 3.x есть новый доступный модуль, называемый kodein-conf . Это позволяет создать модифицируемый экземпляр Kodein (до тех пор, пока вы его модифицируете до завершения первой инъекции), а также содержит глобальный экземпляр Kodein для совместного использования, если это необходимо. Это противоречит нормальному экземпляру Kodein, который должен иметь все привязки, определенные во время построения и никогда не могут быть изменены.

Использование предопределенного глобального так же просто, как ссылка на Kodein.global . И он работает так же, как любой настраиваемый экземпляр Kodein:

 Kodein.global.addImport(someModule) // add other modules to it val something: SomethingCool = Kodein.global.instance() // inject from it 

Если вы хотите создать свой собственный глобальный:

 val kodeinGlobal = ConfigurableKodein() 

Подробнее о ConfigurableKodein читайте в документах Kodein 3.x для ConfigurableKodein и о предопределенном глобальном экземпляре . Комплекс God: One True Kodein

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

 class DefaultSomeService(): SomeService, KodeinGlobalAware { val mapper: ObjectMapper = instance() // ... } 

Если у вас есть случай (например, тестирование), где вы хотите использовать глобальный экземпляр, если он не переопределен конкретным экземпляром, вы можете сделать что-то похожее:

 class DefaultSomeService(override val kodein: Kodein = Kodein.global): SomeService, KodeinAware { val mapper: ObjectMapper = instance() // ... } 

Которая использует интерфейс KodeinAware и переопределяет его абстрактную переменную-член kodein чтобы сделать тот же прозрачный тип инъекции внутри класса, при этом по умолчанию используется global экземпляр.

Если вы хотите только ввести Kodein, является ли это глобальным экземпляром или конкретным, см.: Инъекция экземпляров Kodein в объявлениях привязки в качестве альтернативы.