Guten Morgen
Ich versuch mir grad eine Factory zu bauen, die mir verschiedene Dialoge handeln soll. Dazu hab ich mir zuerstmal ein einfaches Interfaces gebaut:
Delphi-Quellcode:
Type
IVTDialogCall = Interface
['{6EB35D36-EE58-43A3-814E-1173DCA9CBCF}']
function Call(var value:TValue):boolean;
End;
Dafür dann eine Basis-Klasse die wie folgt aussieht:
Delphi-Quellcode:
TVTDialogBase = Class(TInterfacedPersistent,IVTDialogCall)
private
protected
//Must be overridend by a descend class
Procedure BeforeCall(sender:TVTDialogBase;var value:TValue);virtual;
Procedure AfterCall(sender:TVTDialogBase;var value:TValue;callresult:boolean);virtual;
function Execute(var value:TValue):boolean;virtual;abstract;
public
function Call(var value:TValue):boolean;
published
End;
Jeder spezifische Dialog leitet sich von dieser Basisklasse ab:
Delphi-Quellcode:
TVTColorDialog = Class(TVTDialogBase)
private
fdlg : TColorDialog;
protected
Procedure BeforeCall(sender:TVTDialogBase;var value:TValue);override;
procedure AfterCall(sender:TVTDialogBase;var value:TValue;CallResult:boolean);override;
function Execute(var value:TValue):boolean;override;
public
published
End;
Jede Klasse registriert sich im Initialization abschnitt bei der Factory-Klasse. Soweit tut das ganze.
Delphi-Quellcode:
Class function DialogManager.CallDialog(AName: string; var value: TValue):boolean;
var
intf : IVTDialogCall;
dm : TDialogItem;
begin
result := false;
if not (fdialogs.ContainsKey(AName)) then exit;
dm := fdialogs[AName];
if (dm.Ainst = NIL) then
begin
dm.AInst := CreateInstance(dm.AClass);
fdialogs.AddOrSetValue(Aname,dm);
end;
if (dm.AInst <> NIL) then
begin
dm.AInst := CreateInstance(dm.AClass);
fdialogs.AddOrSetValue(Aname,dm);
end;
Supports(dm.Ainst,IVTDialogCall,intf);
if (intf <> NIL) then
result := intf.Call(value);
end;
Diese Methode der Factory implentiert jetzt den Aufruf des Dialoges. Dabei ruft CreateInstance via
RTTI den Constructor der Dialog-Klasse auf. Diese wird gespeichert, um zu vermeiden das die Klasse jedesmal neu erzeugt
werden muss. Nu kracht es allerdings beim Supports mit einer Zugriffsverletzung, was ich so nicht ganz
nachvollziehen kann. Den dm.AInst ist definitiv eine Instanz der Klasse TVTColorDialog (sagt mir der Debugger).
Zusatzinfo:
Das Problem tritt auf, seit ich TVTBaseDialog nicht mehr von TInterfacedObject sonder jetzt von TInterfacedPersistent ableite. Der Grund dafür ist schlicht das ich die Instanzen selbst verwalte und mir die automatische Verwaltung (Referenzzählung usw.) nicht brauche.
Hier noch die Methode CreateInstanz:
Delphi-Quellcode:
var
ctx : TRttiContext;
rt : TRttiType;
rm : TRttiMethod;
begin
ctx := TRttiContext.create;
rt := ctx.GetType(AClass.ClassInfo);
for rm in rt.GetDeclaredMethods do
begin
if (rm.IsConstructor) then
begin
result := rm.Invoke(AClass,[]).AsObject as TInterfacedPersistent;
break;
end;
end;
ctx.Free;
end;
Kann mir jemand sagen wo das Problem liegt ?