Взгляните на Guice (и Dagger) для нового проекта. В каждом уроке Guice, который я видел до сих пор, показан инжектор, созданный в точке, где разработчику нужен DI для создания экземпляра объекта.
Типичный пример, видимый в Интернете:
public static void main(String[] args) {
Injector injector = Guice.createInjector(new BasicModule());
Communication comms = injector.getInstance(Communication.class);
}
Для меня это противоречит цели DI - везде, где требуется экземпляр, вы ie экземпляра для модулей, которые определяют, как его создать.
Есть ли способ попросить Guice создать экземпляр класса who, модуль (граф зависимостей) которого был ранее определен для Guice (например, при запуске приложения?).
Я использую фреймворк Dropwizard.io, поэтому бывают ситуации, когда у меня нет полного контроля над созданием класса, но я хочу иметь возможность смоделировать зависимости, на которые я ссылаюсь в этом классе.
Точно то же самое относится и к Dagger - я буду признателен за примеры для обоих / *. 1012 *
Редактировать: Я работал с несколькими DI-фреймворками в. NET более годы, поэтому я собираюсь привести пример того, что я пытаюсь сделать, основываясь на одном из них.
Например, в реализации ASP. NET Core DI, на службе При запуске вы определяете сервисы, которые вы хотите, чтобы DI мог создавать. Обычно вы будете просить DI дать вам экземпляр, который является реализацией интерфейса. Итак, при запуске:
protected override void ConfigureAdditionalServices(IServiceCollection services)
{
services.AddScoped<ITransactionService, TransactionService>();
}
, где IServiceCollection
- это набор служб, определенных для DI.
Поскольку DI интегрирован с каркасом ASP. NET с этого момента вы обычно можете определить конструктор, который принимает ITransactionService
, и DI предоставит его вам.
Однако, если вы использовали DI в платформе, которая не знала об этом, вам понадобился бы доступ к текущему экземпляру ServiceProvider, а затем вы могли бы попросить DI создать ваш объект следующим образом:
var transactionService = ServiceProvider.GetService<ITransactionService>();
Я понимаю, что это реализует антишаблон Service Locator , но он по-прежнему имеет то преимущество, что отсоединяет мой код от реализаций конкретного класса и позволяет мне макетировать их для тестирования в запуск приложения.
Итак, вернемся к вопросу Итак, чтобы переформулировать мой вопрос в свете этого контекста, как я могу запросить класс у Guice в какой-то случайной точке моего кода?
Что мне нужно изменить в этом коде, чтобы он работал?
public class TransactionModule extends AbstractModule {
@Override
protected void configure() {
bind(TransactionServiceBase.class).to(TransactionService.class);
}
}
// At startup
Injector injector = Guice.createInjector(new TransactionModule());
// Then, somewhere in the application, to get an instance of TransactionService
TransactionServiceBase transactionService = (TransactionServiceBase)Guice.getInstance(TransactionServiceBase.class);