In einer Factory lasse ich derzeit Klassen als intercepted registrieren und auch erstellen(ähnlich wie beim Standard-Framework SPRING):
Delphi-Quellcode:
type ixx=interface
procedure blub;
end;
tx=class(..,ixx)
procedure blub;virtual;
end;
procedure test;
var x:Ixx;
begin
Tfactory.Reg<Txx>('txx').defaultfor<ixx>.Interceptedby(Txxintercept).Interceptedby(Txx2intercept); //auch multiple interceptions sind derzeit möglich. Im Allgemeinen wird das hier durch den Gebrauch von Attributen abgekürzt, soll aber der darstellung dienen.
//interceptedby sucht die entsprechende Klasse raus, erstellt ein Interceptor-Objekt (vmi.proxify(obj)) und hinterlegt dieses in einer der 'txx'-Registrierung zugehörigen liste.
//get object
X := Tfactory.New<ixx>;
//do something
X.Blub;
x:=nil;
end;
Soweit so gut.
Nur, wenn ich jetzt allerdings nicht per unreg<> die klasse und alle zugehörigen Interceptor-objekte lösche:
Delphi-Quellcode:
Var
Reg := Tfactory.Registrations['
txx'];
Var
I := High(Reg.Interceptors);
While I >= 0
Do
Begin
Var
Proxy := Reg.Interceptors[I];
If Assigned(Proxy)
Then
Begin
Proxy.Unproxify(X);
//vmi.unproxify...
Proxy :=
Nil;
End;
Dec(I);
End;
tfactory.unreg<txx>;
, bekomme ich natürlich Speicherlöcher.
Folgendes drängt sich dann auf:
Die Factory / der Container weiss (bisher) nicht um jedes von ihr erstelltes Objekt (zzt nur um die Singletons).
Wie wäre denn denkbar, dass sich ein/ mehrere interceptor beim aufruf von
Txx.destroy
selber mitfreigibt bzw die Interception auflöst, was ja genügt, wenn die Freigabe bei unreg<> passiert? krieg ich das irgendwie an Tobject attached? oder muss ich auf die Standard-Freigabe mit destroy / nil verzichten und ALLE Instanzen auch im Container registrieren?
Folgender interceptor scheint auf den ersten Blick zu funktionieren, allerdings nur, wenn alle abgeleiteten Klassen mit destructor (zb
Delphi-Quellcode:
{...}
Tfactory.Reg<Tobjectinterceptor>('basicinterceptor');
{...}
[Interceptor('basicinterceptor')]
ty=class(tx)
destructor destroy;override;
end;
ebenfalls annotiert / intercepted werden. Das erscheint mir seltsam.
Delphi-Quellcode:
Constructor Tobjectinterceptor.Create(Aclass: Tclass);
Begin
Inherited;
Onbefore :=
Procedure(Instance: TObject; Method: TRttiMethod;
Const Args: TArray<TValue>; Out DoInvoke: Boolean; Out Result: TValue)
Begin
Doinvoke := True;
If Lowercase(Method.Name) = 'freeinstance'
Then
If Assigned(Vmi)
Then
Try
Vmi.OnBefore := Nil;
Vmi.OnAfter := NiL;
Vmi.OnException := Nil;
Vmi.Unproxify(Target);
Finally
End;
End;
End;