Как да накарате уеб модул да знае собственика откъде е бил извикан?

Работя на HTTP сървър и използвам TIdHTTPWebBrokerBridge на Indy с TWebModule. Капсулирам цялата функционалност на сървъра в един единствен компонент и това включва компонента Indy Server и съответния му уеб модул. Въпреки това имам някои проблеми да разбера как да накарам уеб модула да знае компонента, от който е извикан.

Да предположим, че имам този компонент:

type
  TMyComponent = class(TComponent)
  private
    FServer: TIdHTTPWebBrokerBridge;
  end;

implementation

uses
  MyWebModule;

Знам, че трябва да инициализирам това, като настроя манипулатора на заявки, и се погрижих за това, като добавих раздел initialization към този модул:

initialization
  if WebRequestHandler <> nil then
    WebRequestHandler.WebModuleClass:= WebModuleClass;

След това имам класа на уеб модула в отделна единица:

uses
  MyWebServer;

type
  TMyWebModule = class(TWebModule)
  private
    FOwner: TMyComponent;
  end;

Обърнете внимание на частното поле, което имам в този уеб модул FOwner: TMyComponent. Това е мястото, където имам проблеми да разбера къде да отида. Как да присвоя това на подходящия собственик? Уеб модулът се създава и управлява автоматично от HTTP сървъра на Indy, така че, доколкото знам, нямам никакъв контрол, за да задам подобно нещо.

Причината, поради която трябва да имам достъп до неговия собственик, е, че там имам зададени свойства, които уеб модулът трябва да може да чете. Например, едно свойство, което имам на моя компонент, е RootDir, което е главна директория, където да чета/записвам файлове. Трябва да мога да чета това свойство от уеб модула.

Как мога да накарам уеб модула да може да чете свойствата на своя компонент собственик? Или като цяло, как мога да присвоя това лично поле FOwner на екземпляра на моя компонент, откъдето е инстанциран?


person Jerry Dodge    schedule 27.02.2013    source източник
comment
Защо е важно да знаем кой го е извикал? Какво прави с тази информация? Склонен съм да следвам мантрата, обаждащият се може да знае много за това, което вика, но извиканият никога не трябва да знае нищо за това кой го вика. Помага да се запазят нещата отделени.   -  person Marjan Venema    schedule 27.02.2013
comment
Звучи като проблем, който не можете да имате, ако използвате xxm.sf.net   -  person Stijn Sanders    schedule 27.02.2013
comment
@Marjan Обикновено държа нещата отделени, но в този сценарий как иначе уеб модулът трябва да знае своите настройки? Тъй като всичко е обвито в този компонент и свойствата на компонента са мястото, където тази информация се съхранява основно, как иначе уеб модулът би могъл да знае тези настройки? Вярвам, че отговорът ми по-долу е единственото легитимно решение за този сценарий. И в моя случай двете единици са пряко свързани една с друга, така че не е необходимо да се отделят, те са предназначени една за друга.   -  person Jerry Dodge    schedule 27.02.2013
comment
Това, което имаме, е наследник на TWebModule, който просто изпраща неща и модулът регистрира нашия клас с WebRequestHandler. След това имаме THTTPServer, който обединява (точно както правите вие, но в нормален клас, а не компонент) webbrokerbridge. Мостът е създаден с nil като негов собственик и веднага след като мостът е създаден, ние регистрираме нашия наследник на уебмодула в него, като използваме метода RegisterWebModuleClass на предшественика на моста TIdHTTPWebBrokerBridge. Работи като чар... :)   -  person Marjan Venema    schedule 28.02.2013


Отговори (1)


Открих отговора си малко след като зададох този въпрос

Тъй като не се препоръчва да създавате множество екземпляри на TIdHTTPWebBrokerBridge, не е необходимо да се притеснявате за съществуването на множество различни екземпляри на TMyComponent. Трябва обаче да извършите собствена проверка, за да се уверите, че не съществуват множество екземпляри. Но тъй като имате само един екземпляр на този компонент, можете да се чувствате сигурни, като декларирате глобална променлива в модула на вашия компонент и я излагате на вашия уеб модул.

Не просто декларирайте глобална var променлива директно в interface на вашето устройство. Вместо това трябва да защитите това...

function MyComponent: TMyComponent;

implementation

uses
  MyWebModule;

var
  _MyComponent: TMyComponent;

function MyComponent: TMyComponent;
begin
  Result:= _MyComponent;
end;

constructor TMyComponent.Create(AOwner: TComponent);
begin
  inherited;
  _MyComponent:= Self;
end;

destructor TMyComponent.Destroy;
begin
  _MyComponent:= nil;
  inherited;
end;

initialization
  _MyComponent:= nil;
  if WebRequestHandler <> nil then
    WebRequestHandler.WebModuleClass:= WebModuleClass;
end.
person Jerry Dodge    schedule 27.02.2013
comment
Като странична бележка също не се препоръчва този компонент на Indy да се увива в компонент по такъв начин, но въпреки това го правя. Друго решение би било да не излагате компонента изобщо, да го оставите частен и да добавите InitMyServer и UnInitMyServer процедури. - person Jerry Dodge; 27.02.2013