TVirtualMethodInterceptor cannot be used for AfterConstruction
skybuck2000 <[email protected]> Sun, 30 Jan 2022 14:32:25 -0800 (PST)
| Newsgroups | alt.comp.lang.borland-delphi |
|---|---|
| Message-ID | <[email protected]> |
If TStream.AfterConstruction could be overriden then all stream objects could be captured, actually all objects could be captured.
Unfortunately VirtualMethodInterception seems to be wrongly designed and can only act on already existing instances, instead of a class.
This example from the documentation completely ignores construction of objects and therefore the AfterConstruction method which is also virtual:
(See down below for suggestion how to fix Delphi in future):
uses
SysUtils,
Rtti;
type
TFoo = class
// Frob doubles x and returns the new x + 10
function Frob(var x: Integer): Integer; virtual;
end;
function TFoo.Frob(var x: Integer): Integer;
begin
x := x * 2;
Result := x + 10;
end;
procedure WorkWithFoo(Foo: TFoo);
var
a, b: Integer;
begin
a := 10;
Writeln(' [WorkWithFoo] before: a = ', a);
try
b := Foo.Frob(a);
Writeln(' [WorkWithFoo] Result = ', b);
Writeln(' [WorkWithFoo] after: a = ', a);
except
on e: Exception do
Writeln(' Exception: ', e.ClassName);
end;
end;
procedure P;
var
foo: TFoo;
vmi: TVirtualMethodInterceptor;
begin
vmi := nil;
foo := TFoo.Create;
try
Writeln('Before hackery:');
WorkWithFoo(foo);
vmi := TVirtualMethodInterceptor.Create(foo.ClassType);
vmi.OnBefore := procedure(Instance: TObject; Method: TRttiMethod;
const Args: TArray<TValue>; out DoInvoke: Boolean; out Result: TValue)
var
i: Integer;
begin
Write('[OnBefore] Calling ', Method.Name, ' with args: ');
for i := 0 to Length(Args) - 1 do
Write(Args[i].ToString, ' ');
Writeln;
end;
// Change foo's metaclass pointer to our new dynamically derived
// and intercepted descendant
vmi.Proxify(foo);
Writeln('After interception:');
WorkWithFoo(foo);
finally
foo.Free;
vmi.Free;
end;
end;
begin
P;
readln; // To see what's in console before it goes away.
end.
This should be fixed in a subsequent version of Delphi if possible.
Main issue seems to be:
procedure Proxify(AInstance: TObject);
It should be possible to pass a class as well.
And then call some kind of constructor or other method to create these derived instances.
So that AfterConstruction can also be intercepted !
Bye,
Skybuck.