Home > Back-end >  How to access Tag property
How to access Tag property

Time:12-15

How can I access HTTPRIO.Tag previously assigned from, for instance, the HTTPRIO.OnBeforeExecute event? Is it possible?

Let's say I have something like this:

procedure TForm1.HTTPRIO1BeforeExecute(const MethodName: string; SOAPRequest: TStream);
begin
  if THHPRIO(Sender).Tag = 99 then
    ...some code...
end;

But I don't have a Sender on any of the THTTPRIO events.

CodePudding user response:

Since you are assigning events to multiple THTTPRIO objects, but don't have access to a Sender parameter in the events (bad design on THTTPRIO's author), one workaround is to use the TMethod record to manipulate the event handler's Self pointer to point at the THTTPRIO object rather than the TForm1 object, eg:

procedure TForm1.FormCreate(Sender: TObject);
var
  M: TBeforeExecuteEvent;
begin
  M := HTTPRIOBeforeExecute;
  TMethod(M).Data := HTTPRIO1;
  HTTPRIO1.OnBeforeExecute := M;

  M := HTTPRIOBeforeExecute;
  TMethod(M).Data := HTTPRIO2;
  HTTPRIO2.OnBeforeExecute := M;

  // and so on ...
end;

And then you can type-cast Self inside the events, eg:

procedure TForm1.HTTPRIOBeforeExecute(const MethodName: string; SOAPRequest: TStream);
begin
  if THTTPRIO(Self).Tag = 99 then
    ...some code...
end;

Alternatively, you can use a standalone procedure (or class static method) with an explicit parameter for the Self pointer, eg:

procedure HTTPRIOBeforeExecute(Sender: THTTPRIO; const MethodName: string; SOAPRequest: TStream);
begin
  if Sender.Tag = 99 then
    ...some code...
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  M: TBeforeExecuteEvent;
begin
  TMethod(M).Data := HTTPRIO1;
  TMethod(M).Code := @HTTPRIOBeforeExecute;
  HTTPRIO1.OnBeforeExecute := M;

  TMethod(M).Data := HTTPRIO2;
  TMethod(M).Code := @HTTPRIOBeforeExecute;
  HTTPRIO2.OnBeforeExecute := M;

  // and so on ...
end;

CodePudding user response:

While Remy's solution works, leaving the code in TForm1 leaves you at risk of accidentally referencing fields from TForm1 in TForm1.HTTPRIOBeforeExecute, and since "Self" isn't a TForm1 anymore, that would crash/corrupt memory.

I would personally use the following approach :

THTTPRIOMethodHolder = class(THTTPRIO)
public
  procedure HTTPRIOBeforeExecute(const MethodName: string; SOAPRequest: TStream);
end;

procedure THTTPRIOMethodHolder.HTTPRIOBeforeExecute(const MethodName: string; SOAPRequest: TStream);
begin
  if {self.}Tag = 99 then
    ...some code...
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  HTTPRIO1.OnBeforeExecute := THTTPRIOMethodHolder(HTTPRIO1).HTTPRIOBeforeExecute;
  HTTPRIO2.OnBeforeExecute := THTTPRIOMethodHolder(HTTPRIO2).HTTPRIOBeforeExecute;
end;

This should work as long as you don't add fields in THTTPRIOMethodHolder and HTTPRIOBeforeExecute is not made virtual.

  • Related