2012-03-31 2 views
8

Возможно зарегистрировать класс с параметром, который, как ожидается, будет передан от точки создания?delphi - как передать параметр из объекта-указателя в конструктор в рамки впрыска зависимостей spring4d?

Я знаю, что это можно сделать что-то вроде этого:

GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>. 
AsTransient.DelegateTo(
    function: TUserProcessor 
    begin 
     Result := TUserProcessor.Create(GetCurrentUser); 
    end 
); 

Но параметры переплетены в контекст выполнения, когда контейнер регистрируется и не там, где объект прибудет-х intantiated.

Что-то подобное возможно, например?

GlobalContainer.Resolve<IMathService>([FCurrentUser]); 

Я знаю, что некоторый peoble адвокат имеет очень простые конструктор, но бывают случаи, когда параметр конструктора явно выглядит путь:

  1. Объект построен нуждается параметром объекта для работы, поэтому ссылка должна быть удовлетворена. Параметр также делает это ограничение более очевидным, глядя на класс.

  2. Вы можете назначить ссылку в методе или свойстве, а также повысить и исключить в каждом другом методе, если вы попытаетесь использовать объект без предварительного присваивания. Мне не нравится писать этот тип кода, это просто тратить время, просто используйте параметр конструктора и проверьте там. Меньше кода, тем лучше ИМО.

  3. Также передаваемый объект является локальным для объекта, который создает новый объект с использованием контейнера (например, объекта Transaction) и имеет некоторое состояние (это не новый объект, который я могу получить с контейнером).

+0

Я не знаю перегрузку '' TContainer.Resolve принимающей параметр массива в Spring4D. Я что-то пропустил? – menjaraz

+0

@menjaraz Это было просто и идея о том, как это можно реализовать (наверняка это может быть donde с RTTI) –

+0

Хорошо, это звучит как запрос функции. Почему бы не опубликовать это также в [spring4d Google Group] (http://groups.google.com/group/spring4d)? – menjaraz

ответ

7

Я добавил переопределитель, как в Unity.

Таким образом, вы можете написать:

program Demo; 

{$APPTYPE CONSOLE} 

uses 
    Classes, 
    Spring.Container, 
    Spring.Container.Resolvers; 

type 
    IUserUpgrader = interface 
    ['{ADC36759-6E40-417D-B6F7-5DCADF8B9C07}'] 
    end; 

    TUser = class(TObject); 

    TUserProcessor = class(TInterfacedObject, IUserUpgrader) 
    public 
    constructor Create(AUser: TUser); 
    end; 

constructor TUserProcessor.Create(AUser: TUser); 
begin 
    Writeln('called constructor with passed user'); 
end; 

begin 
    GlobalContainer.RegisterType<TUserProcessor>.Implements<IUserUpgrader>; 
    GlobalContainer.Build; 

    GlobalContainer.Resolve<IUserUpgrader>(
    TOrderedParametersOverride.Create([TUser.Create])); 

    GlobalContainer.Resolve<IUserUpgrader>(
    TParameterOverride.Create('AUser', TUser.Create)); 

    Readln; 
end. 
0

Вы можете проверить эту тему: https://forums.embarcadero.com/message.jspa?messageID=440741

Я сделал реализацию на это в рамках и использовать его в своем коде. Если вы этого захотите, я отправлю его вам. Имейте в виду, что это не так, как это может быть сделано, когда и если они добавят такие функции в кодовую базу. У Баокуана есть мой код.

Эта реализация также обрабатывается, если вы пытаетесь разрешить без всех необходимых параметров и дает вам исключение, показывающее отсутствующие параметры.

Вы можете использовать его как это:

ServiceLocator.GetService<ISomeObj>(ServiceParameters['paramname1',value1]['paramname2',value2]..); 

Значение сохраняется как TValue и может быть что угодно.

Регистрация параметра с классом осуществляется с атрибутами, как это:

private 
    [ContainerParameter('paramname1')] 
    FYourValue1: ...; 
    [ContainerParameter('paramname2')] 
    FYourValue2: ..; 

Вы также можете сделать

[ContainerParameter] 
FYourValue1:.. 

Но тогда ваш параметр имеет «FYourValue1» в качестве имени.

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

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