Задать вопрос
@nslim13

Dependency Injection и Spring4d?

Читаю книгу Ника Ходжеса Dependency Injection in DELPHI. В главе "Registering Factories" рассматривается такой пример:
Есть интерфейс:
ICoffeeMaker = interface
['{73436E03-EF65-44F5-9606-F706156CBEB5}']
  procedure MakeCoffee;
end;

...и класс его реализующий:
type
  TCoffeeMaker = class(TInterfacedObject, ICoffeeMaker)
    private
      FCoffeeBrand: string;
      FBrewingMinutes: integer;
    public
      constructor Create(const aCoffeeBrand: string; const aBrewingMinutes: integer);
      procedure MakeCoffee;
    end;

constructor TCoffeeMaker.Create(const aCoffeeBrand: string; const aBrewingMinutes: integer);
begin
  inherited Create;
  FCoffeeBrand := aCoffeeBrand;
  FBrewingMinutes := aBrewingMinutes;
end;

procedure TCoffeeMaker.MakeCoffee;
begin
  WriteLn('Pour hot water over the ', FCoffeeBrand, ' so that it brews for ', FBrewingMinutes, ' minutes.');
end;

Далее декларируется функция-фабрика для создания экземпляра ICoffeeMaker:
type
  {$M+}
  TCoffeeMakerFactory = reference to function(const aCoffeeBrand: string; const aBrewingMinutes: integer): ICoffeeMaker;
  {$M-}

...и всё это дело регистрируется в контейнере:
procedure RegisterStuff(aContainer: TContainer);
begin
  aContainer.RegisterType<ICoffeeMaker, TCoffeeMaker>.AsDefault;
  aContainer.RegisterFactory<TCoffeeMakerFactory>;
  aContainer.Build;
end;

И далее приводит код основной программы:
var
  CoffeeName: string;
  BrewingMinutes: integer;
  CoffeeMakerFactory: TCoffeeMakerFactory;
  CoffeeMaker: ICoffeeMaker;
begin
  Write('What kind of coffee do you want to make? ');
  ReadLn(CoffeeName);

  Write('How many minutes? ');
  ReadLn(BrewingMinutes);

  CoffeeMakerFactory := Container.Resolve<TCoffeeMakerFactory>();
  CoffeeMaker := CoffeeMakerFactory(CoffeeName, BrewingMinutes);
  CoffeeMaker.MakeCoffee;
end;

Автор пишет, что регистрировать TCoffeeMaker в контейнере, в принципе, не обязательно. Но вдруг у нас будет какой-нибудь класс TKitchen, у которого в зависимостях будет ICoffeeMaker.
Вопрос в следующем:
Что если действительно есть класс TKitchen, реализующий интерфейс IKitchen, который в конструкторе принимает параметром ICofeeMaker? Получается я его зарегистрирую в контейнере:
begin
  //...
  aContainer.RegisterType<IKitchen, TKitchen>;
  //...
end;

...и далее создам:
begin
  //...
  Kitchen := Container.Resolve<IKitchen>();
  //...
end;

Как в таком случае настраивается передаваемый в его конструктор экземпляр ICoffeeMaker?
  • Вопрос задан
  • 188 просмотров
Подписаться 1 Средний 1 комментарий
Пригласить эксперта
Ответы на вопрос 1
OCTAGRAM
@OCTAGRAM
Смущает конструкция

aContainer.RegisterFactory<TCoffeeMakerFactory>;

Здесь ведь даже не передана никакая реализация функции конструктором.

И от фабрики я бы ожидал, что у неё просто нет параметров, которые движок DI не мог бы подставить. То есть,

TFunc<ICofeeMaker>

А если параметры всё же есть, то либо движок DI должен поискать у себя фабрику строки и целого цисла, либо эти параметры задаются RTTI атрибутами. Или задаются при регистрации какой-то из фабрик, ICoffeeMaker или IKitchen.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

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