2009-08-06 5 views
2

Bezug zu meinen letzten question, ich habe jetzt folgendes Problem:Cast von TObject Schnittstelle Typ

function TNodeFactory <T>.CreateNode (ID : Integer) : INodeInterface <T>; 
var 
    NodeClass : TClass; 
begin 
    NodeClass := FindRegisteredClass (ID); 
    Result := NodeClass.Create;  
end; 

Dies ergibt einen Compiler-Fehler:

E2010 Incompatible Types: 'INodeInterface<TNodeFactory<T>.T>' and 'TObject' 

Ein Abguss nicht arbeiten.

Was fehlt mir hier?

EDIT: Die aktuelle Implementierung

TNodeFactory <T> = class 
private 
    type 
    TRegisteredNodeType = record 
     ID : Integer; 
     NodeClass : TClass; 
    end; 
private 
    FNodeTypeList : TList <TRegisteredNodeType> 
public 
    procedure RegisterNodeType (ID : Integer; NodeClass : TClass); 
    function CreateNode (ID : Integer) : INodeInterface <T>; 
end; 

procedure TNodeFactory <T>.RegisterNodeType (ID : Integer; NodeClass : TClass); 
var 
    RegisteredType : TRegisteredNodeType; 
begin 
    RegisteredType.ID := ID; 
    RegisteredType.NodeClass := NodeClass; 
    FNodeTypeList.Add (RegisteredType); 
end; 

function TNodeFactory <T>.CreateNode (ID : Integer); 
var 
    RegisteredType : TRegisteredNodeType; 
begin 
    for RegisteredType in FNodeTypeList do 
    if (RegisteredType.ID = ID) then 
     Exit (RegisteredType.NodeClass.Create); 
    raise EInvalidNodeType.Create ('No node type with ID ' + IntToStr (ID) + ' registered'); 
end; 

(vereinfachten und entfernt Fehlerprüfungen)

+0

NodeClass ein TClass ist. Wenn Sie NodeClass erstellen, handelt es sich um ein reines TObject, nicht um ein INodeInterface. Sie müssen uns Ihre Implementierung von RegisterClass und FindRegisteredClass zeigen. –

+0

hinzugefügt meine Frage – jpfollenius

+1

Sie könnten versuchen * Ergebnis: = TInterfacedObject (RegisteredType.NodeClass) .Create als INodeInterface * –

Antwort

3

Das Problem ist, dass NodeClass eine TClass ist. Wenn Sie NodeClass erstellen, handelt es sich um ein reines TObject, nicht um ein INodeInterface.

könnten Sie

versuchen
Result := TInterfacedObject(RegisteredType.NodeClass).Create as INodeInterface 

oder RegisterNodeType

type 
    TInterfacedObjectClass = class of TInterfacedObject; 
... 
procedure RegisteredNodeType...(ID: Integer; NodeClass : TInterfacedObjectClass); 

zu

ändern und zurück

Result := RegisteredType.NodeClass.Create as INodeInterface. 
0

Lassen Sie mich meine Antwort mit diesen Offenbarungs beginnen: Ich bin nicht, dass bei der Verwendung von Vorlagen in Delphi vertraut .

Sie erhalten den Compilerfehler, weil Sie versuchen, NodeClass zurückzugeben, die als eine Instanz von TClass definiert ist. Die Funktion erwartet jedoch, dass Sie eine Instanz einer Klasse zurückgeben, die INodeInterface implementiert. Möglicherweise können Sie dieses Problem mit so etwas wie dieses

Result := INodeInterface(NodeClass.Create);  

oder

function TNodeFactory <T>.CreateNode (ID : Integer) : INodeInterface <T>; 
var 
    NodeClass : TClass; 
    NodeInterface: INodeInterface; 
begin 
    NodeClass := FindRegisteredClass (ID); 
    NodeInterface:= NodeClass.Create; 
    Result := NodeInterface;  
end; 

dies die richtige Antwort sein könnte nicht lösen, aber ich hoffe, dass diese Ihnen zur Lösung führen können.

+0

Wie ich in der Frage sagte: "eine Besetzung funktioniert nicht auch". Und die zweite Version ist IMHO nur eine längere Version des ersten. Danke trotzdem! – jpfollenius

2

Sie müssen die Funktion Supports() verwenden, um eine Schnittstellenreferenz von einem Objekt zu extrahieren. Sie finden es in SysUtils.

Es gibt mehrere überladene Versionen, Sie möchten die Version mit drei Parametern, mit der der dritte Parameter "out" Ihre Schnittstellenreferenz zurückbringt.

+0

Woher kommt diese Methode? Kann nicht in TObject oder in der Delphi-Hilfe gefunden werden ... – jpfollenius

2

In Delphi ist ein Interface kein Objekt. Und der Interface-Pointer ist kein Objectpointer, deshalb können Sie ihn nicht darstellen. Sie müssen QueryInterface verwenden und nach der Schnittstelle abfragen.

function QueryInterface(var IID: TGUID; out Obj: Type):HRESULT 

Wenn HRESULT S_OK ist, enthält obj einen Verweis auf die abgefragte Schnittstelle.

Leider behandelt Delphi (Win32) Schnittstellen zu .NET/Java.

+0

@Smasher: Wenn Sie sich den Code für Supports() ansehen, werden Sie feststellen, dass er QueryInterface() aufruft, so dass Sie eines verwenden können. – LachlanG

+0

+1 Habe es nicht versucht, da Lievens Lösung für mich funktioniert. Aber danke! – jpfollenius

Verwandte Themen