Ich habe hier eine generische Klassen/Interface Definition, die von
TComponent abgeleitet ist.
Wie bekomme ich die Klasse jetzt dazu eine passende Instanz zu erzeugen?
TGenClass<T:Class, Constructor> = class
sagt ja nur aus, dass die Klasse T einen
parameterlosen Constructor hat.
TComponent hat aber einen Constructor
mit Parameter (obwohl ich dem ledigleich ein schnödes nil mitgeben würde).
Das
T.Create;
findet der Compiler gut, aber es ist nicht so wie ich das möchte, denn
Delphi-Quellcode:
var
MyButton : IGenericLink<TButton>;
begin
MyButton := TGenericLink<TButton>.Create;
MyButton.Link.OnClick := ButtonClick; // hier rummst es, und das soll es nicht
end;
und
T.Create(nil);
findet der Compiler total blöde
Sinn und Zweck dieser Übung ist das Binding von Komponenten einer Form zu einer Controller-
Unit.
Dabei soll es die Controller-
Unit aushalten, wenn auf der Form nicht alle Komponenten vorhanden sind. (Darum hält TGenericLink eben ein Dummy-Object vor, auf das zugegriffen wird, wenn kein gültiger Link gebildet werden konnte).
Wer kann mir da mal auf den lahmen Gaul helfen?
Die ganze
Unit mal zum überfliegen:
Delphi-Quellcode:
unit FormBinding;
interface
uses
Classes;
type
IGenericLink<T: TComponent,
Constructor> =
interface
['
{7650F483-5FDD-431F-96D1-65536B127BB5}']
function GetLink: T;
procedure SetLink(
const Value: T);
property Link: T
read GetLink
write SetLink;
procedure LinkTo(
const Value: TComponent);
overload;
procedure LinkTo(
const Owner: TComponent;
const ComponentName:
string);
overload;
function IsLinked: Boolean;
function GetOnLinkChanged: TNotifyEvent;
procedure SetOnLinkChanged(
const Value: TNotifyEvent);
property OnLinkChanged: TNotifyEvent
read GetOnLinkChanged
write SetOnLinkChanged;
end;
TGenericLink<T: TComponent,
Constructor> =
class(TInterfacedObject,
IGenericLink<T>)
private
fInt: T;
fExt: T;
fOnLinkChanged: TNotifyEvent;
function GetLink: T;
procedure SetLink(
const Value: T);
function GetOnLinkChanged: TNotifyEvent;
procedure SetOnLinkChanged(
const Value: TNotifyEvent);
public
constructor Create;
destructor Destroy;
override;
property Link: T
read GetLink
write SetLink;
procedure LinkTo(
const Value: TComponent);
overload;
procedure LinkTo(
const Owner: TComponent;
const ComponentName:
string);
overload;
function IsLinked: Boolean;
property OnLinkChanged: TNotifyEvent
read GetOnLinkChanged
write SetOnLinkChanged;
end;
implementation
{ TGenericLink<T> }
constructor TGenericLink<T>.Create;
begin
inherited Create;
fInt := T.Create;
// <<-- ???
end;
destructor TGenericLink<T>.Destroy;
begin
fInt.Free;
inherited;
end;
function TGenericLink<T>.GetLink: T;
begin
if Assigned(fExt)
then
Result := fExt
else
Result := fInt;
end;
function TGenericLink<T>.GetOnLinkChanged: TNotifyEvent;
begin
Result := fOnLinkChanged;
end;
function TGenericLink<T>.IsLinked: Boolean;
begin
Result := Assigned(fExt);
end;
procedure TGenericLink<T>.LinkTo(
const Owner: TComponent;
const ComponentName:
string);
begin
LinkTo(Owner.FindComponent(ComponentName));
end;
procedure TGenericLink<T>.LinkTo(
const Value: TComponent);
begin
if Assigned(Value)
and Value.InheritsFrom(T)
then
SetLink(Value)
else
SetLink(
nil);
end;
procedure TGenericLink<T>.SetLink(
const Value: T);
begin
fExt := Value;
if Assigned(OnLinkChanged)
then
OnLinkChanged(Self);
end;
procedure TGenericLink<T>.SetOnLinkChanged(
const Value: TNotifyEvent);
begin
fOnLinkChanged := Value;
end;
end.