2016-03-10 1 views
3

Я борюсь с конструкторской инъекцией Spring4D. В определенном классе я хочу ввести конкретную реализацию (по имени) интерфейса в конструктор.«Неудовлетворенный конструктор» при впрыске конструктора с Spring4D

Посмотрите на это:

IListFactory = interface 
    ['{40...29}'] 
    function GetList : IListOfSomething; 
end; 

ICiderPress = interface 
    ['{50...10}'] 
    procedure Press; 
end; 

TAppleListFactory = class(TInterfacedObject, IListFactory) 
    function GetList : IListOfSomething; 
end; 

TCiderPress = class(TInterfacedObject, ICiderPress) 
private 
    FListFactory : IListFactory; 
public 
    constructor Create(const ListFactory : IListFactory); 

    procedure Press; 
end; 

implementation 

function TCiderPress.Create(const ListFactory : IListFactory); 
begin 
    FListFactory := ListFactory; 
end; 

procedure TCiderPress.Press; 
begin 
    // Do somtihing with FListFactory 
end; 

initialization 
    GlobalContainer.RegisterType<TAppleListFactory>.Implements<IListFactory>('apple'); 

    GlobalContainer.RegisterType<TCiderPress>.Implements<ICiderPress>; 
end. 

Теперь я получаю экземпляр моей печати с ServiceLocator:

CiderPress := ServiceLocator.GetService<ICiderPress>; 
CiderPress.Press; 

и она отлично работает.

Теперь я добавить второй ListFactory:

TOrangeListFactory = class(TInterfacedObject, IListFactory) 
    function GetList : IListOfSomething; 
end; 

и добавить в регистрирующий

GlobalContainer.RegisterType<TOrangeListFactory>.Implements<IListFactory>('orange'); 

и изменить свой сидр пресс-класс

TCiderPress = class(TInterfacedObject, ICiderPress) 
private 
    FListFactory : IListFactory; 
public 
    [Inject] 
    constructor Create([Inject('apple')]const ListFactory : IListFactory); 

    procedure Press; 
end; 

Проблема в том, что т е р из TCiderPress не вызывается.

Если добавить

GlobalContainer.AddExtension<TActivatorContainerExtension>; 

Я получаю EActivatorException: Неудовлетворенный застройщик по типу: TCiderPress

Что идет не так?

EDIT:

Это работает, если я делегировать строительство так:

GlobalContainer.RegisterType<TCiderPress>.Implements<ICiderPress> 
    .DelegateTo(function : TCiderPress 
     begin 
      Result := TCiderPress.Create(ServiceLocator.GetService<IListFactory>('apple'); 
     end 
    ); 

EDIT2:

Я нашел ошибку! Я должен был включить Spring.Container.Common в интерфейсе использует пункт.

Я использую Delphi XE3 и Spring4D 1.1.3.

+0

Похоже, нам нужен [mcve] –

+1

пример из @mezen работает для меня. Мое настоящее приложение довольно сложно. Я пытаюсь воспроизвести ошибку с минимальным примером. До тех пор, есть ли способ отлаживать инъекцию конструктора? – Mik

+0

Все может быть отлажено. Создание репродукции - это то, как я его отлаживал. –

ответ

5

Это работает для меня:

unit Unit2; 

interface 

uses 
    Spring.Container, 
    Spring.Container.Common; 

type 
    IListOfSomething = interface 
    ['{ACCEF350-5FDE-4D60-BAE0-17F029A669ED}'] 
    end; 


    IListFactory = interface 
    ['{039DE93A-1235-4D75-A8E2-7265765F6E90}'] 
    function GetList : IListOfSomething; 
    end; 

    ICiderPress = interface 
    ['{64C4F565-BB8C-42C0-9584-4F4A21779F52}'] 
    procedure Press; 
    end; 

    TAppleListFactory = class(TInterfacedObject, IListFactory) 
    public 
    function GetList: IListOfSomething; 
    end; 

    TOrangeListFactory = class(TInterfacedObject, IListFactory) 
    public 
    function GetList: IListOfSomething; 
    end; 

    TCiderPress = class(TInterfacedObject, ICiderPress) 
    private 
    FListFactory: IListFactory; 
    public 
    [Inject] 
    constructor Create([Inject('apple')] const ListFactory: IListFactory); 
    procedure Press; 
    end; 

implementation 

constructor TCiderPress.Create(const ListFactory: IListFactory); 
begin 
    FListFactory := ListFactory; 
end; 

procedure TCiderPress.Press; 
begin 
    WriteLn(TObject(FListFactory).ClassName); 
end; 

{ TAppleListFactory } 

function TAppleListFactory.GetList: IListOfSomething; 
begin 
    Result := nil; 
end; 

{ TOrangeListFactory } 

function TOrangeListFactory.GetList: IListOfSomething; 
begin 
    Result := nil; 
end; 

initialization 
    GlobalContainer.RegisterType<TAppleListFactory>.Implements<IListFactory>('apple'); 
    GlobalContainer.RegisterType<TOrangeListFactory>.Implements<IListFactory>('orange'); 
    GlobalContainer.RegisterType<TCiderPress>.Implements<ICiderPress>; 
    GlobalContainer.Build(); 
end. 

и потребляя как

o := GlobalContainer.Resolve<ICiderPress>; 
o.Press(); 
+0

Привет, спасибо за ваш тест. Я думаю, я описал ваш код и подумал, что я сделал то же самое в своем приложении. Я тестировал ваш код в своем приложении, и он работает. Таким образом, нет проблем с версией Delphi или Spring4D. Мне нужно выяснить, где различия между этим примером кода и моим (более сложным) кодом приложения ... – Mik

+1

Ваш пример указывает мне на решение. Мне нужно было включить _Spring.Container.Common_ в предложение uses. – Mik

 Смежные вопросы

  • Нет связанных вопросов^_^