2009-08-06 8 views
2

lié à ma dernière question, j'ai maintenant le problème suivant:Cast de TObject à l'interface de type

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

Cela donne une erreur du compilateur:

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

Un casting ne fonctionne pas trop.

Qu'est-ce qui me manque ici?

EDIT: la mise en œuvre actuelle

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; 

(contrôles d'erreur simplifiés et supprimés)

+0

NodeClass est un TClass. Si vous créez NodeClass, ce sera simplement TObject et non INodeInterface. Vous devrez nous montrer votre implémentation de RegisterClass et FindRegisteredClass. –

+0

ajouté implémentation à ma question – jpfollenius

+1

Vous pouvez essayer * Résultat: = TInterfacedObject (RegisteredType.NodeClass) .Create comme INodeInterface * –

Répondre

3

Le problème est que NodeClass est un TClass. Si vous créez NodeClass, ce sera simplement TObject et non INodeInterface.

Vous pouvez essayer

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

ou changer RegisterNodeType à

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

et retour

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

Permettez-moi de commencer ma réponse à cette divulgateur: Je ne suis pas familier avec l'utilisation de modèles dans Delphi .

Vous obtenez l'erreur de compilation parce que vous essayez de retourner NodeClass qui est définie comme une instance de TClass. Toutefois, la fonction s'attend à ce que vous renvoyiez une instance d'une classe qui implémente INodeInterface. Vous pourriez être en mesure de résoudre ce problème avec quelque chose comme ça

Result := INodeInterface(NodeClass.Create);  

ou

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

Cela pourrait ne pas être la bonne réponse, mais j'espère que cela vous aide à conduire à la solution.

+0

Comme je l'ai dit dans la question: "un casting ne fonctionne pas trop". Et la deuxième version est à mon humble avis une version plus longue de la première. Merci quand même! – jpfollenius

2

Vous devez utiliser la fonction Supports() pour extraire une référence d'interface d'un objet. Vous le trouverez dans SysUtils.

Il existe plusieurs versions surchargées, vous voulez la version à trois paramètres avec laquelle le troisième paramètre "out" vous ramène votre référence d'interface.

+0

D'où vient cette méthode? Vous ne pouvez pas le trouver dans TObject ou dans l'aide de Delphi ... – jpfollenius

2

En Delphi, une interface n'est pas un objet. Et l'Interface-Pointer n'est pas un Objectpointer, c'est pourquoi vous ne pouvez pas les lancer. Vous devez utiliser QueryInterface et interroger l'interface.

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

si HRESULT est S_OK, alors obj contient une référence à l'interface interrogée.

Malheureusement, Delphi (Win32) gère les interfaces différentes de .NET/Java.

+0

@Smasher: Si vous regardez le code pour Supports(), vous verrez qu'il appelle QueryInterface() afin que vous puissiez utiliser l'un ou l'autre. – LachlanG

+0

+1 N'a pas essayé, puisque la solution de Lieven fonctionne pour moi. Mais merci! – jpfollenius

Questions connexes