Einzelnen Beitrag anzeigen

TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
3.060 Beiträge
 
Delphi 10.4 Sydney
 
#1

TGUID von Interface-Instanz herausfinden

  Alt 7. Mai 2014, 10:58
Delphi-Version: XE3
Hallo zusammen,

kann man über die RTTI (Stand XE3) die TGUID einer Interface-Instanz herausfinden?
Ich habe einen Anwendungsfall, bei dem ich eine lebendes Interface-Objekt zu einem generischen Dictionary hinzufügen muss.
Der Key ist dann die TGUID.
Darüber wird dann auch später das betreffende Element/Objekt aus der Liste entfernt.

Ich habe versucht das Ganze in einer übersichtlichen Beispiel-Unit unterzubringen.
Mir geht es konkret darum, die ewig langen if-else-Abfragen mit Supports() in der Methode GetInterfaceGUID zu vermeiden:

Delphi-Quellcode:
unit List;

interface

uses
  System.SysUtils,
  Generics.Collections;

const
  SID_MAIN = '{BCA44697-4841-457B-8161-30A9BDC2A0A0}';
  SID_CHILD1 = '{C8527C3A-EB3C-46C1-94BB-3C9DFB12AF92}';
  SID_CHILD2 = '{A21F5DED-9BEC-4D25-BB7B-21AD3C46FB75}';
  SID_CHILD3 = '{8AE48CFE-2DDA-40C9-901A-660974B5DDA1}';

type
  IMainInterface = interface(IUnknown)
    [SID_MAIN]
  end;

  IChildInterface1 = interface(IUnknown)
    [SID_CHILD1]
  end;

  IChildInterface2 = interface(IUnknown)
    [SID_CHILD2]
  end;

  IChildInterface3 = interface(IUnknown)
    [SID_CHILD3]
  end;

  TMyList = class(TObject)
  private
    FInterfaceList : TDictionary<TGUID, IMainInterface>;
    function GetInterfaceGUID(const AInterfaceInstance : IMainInterface) : TGUID;
  public
    constructor Create;
    destructor Destroy; override;
    function Add(const AInterfaceInstance : IMainInterface) : Boolean;
    function Remove(const AType : TGUID; out AInterfaceInstance : IMainInterface) : Boolean;
  end;

implementation


function TMyList.GetInterfaceGUID(const AInterfaceInstance : IMainInterface) : TGUID;
begin
  Result := IMainInterface;
  // wie geht das hier besser? Irgendwas mit GetTypeInfo von der RTTI oder sowas?
  if Supports(AInterfaceInstance, IChildInterface1) then
  begin
    Result := IChildInterface1;
  end
  else if Supports(AInterfaceInstance, IChildInterface2) then
  begin
    Result := IChildInterface2;
  end
  else if Supports(AInterfaceInstance, IChildInterface3) then
  begin
    Result := IChildInterface3;
  end;
end;

constructor TMyList.Create;
begin
  inherited Create;
  FInterfaceList := TDictionary<TGUID, IMainInterface>.Create;
end;

destructor TMyList.Destroy;
begin
  FInterfaceList.Free;
  inherited Destroy;
end;

function TMyList.Remove(const AType : TGUID; out AInterfaceInstance : IMainInterface) : Boolean;
begin
  Result := FInterfaceList.TryGetValue(AType, AInterfaceInstance);
  if Result then
  begin
    FInterfaceList.Remove(AType);
  end;
end;

function TMyList.Add(const AInterfaceInstance : IMainInterface) : Boolean;
begin
  Result := not FInterfaceList.ContainsValue(AInterfaceInstance);
  if Result then
  begin
    FInterfaceList.Add(GetInterfaceGUID(AInterfaceInstance), AInterfaceInstance);
  end;
end;

end.
Angewendet wird dass dann bspw. so:

Delphi-Quellcode:
type
  TClass1 = class(TInterfacedObject, IChildInterface1, IMainInterface)
  end;

  TClass2 = class(TInterfacedObject, IChildInterface2, IMainInterface)
  end;

  TClass3 = class(TInterfacedObject, IChildInterface3, IMainInterface)
  end;

procedure TForm2.Button1Click(Sender: TObject);
var
  I1 : IMainInterface;
  I2 : IMainInterface;
  I3 : IMainInterface;
  List : TMyList;

begin
  I1 := TClass1.Create;
  I2 := TClass2.Create;
  I3 := TClass3.Create;

  List := TMyList.Create;
  List.Add(I1);
  List.Add(I2);
  List.Add(I3);

  List.Free;
end;

Geändert von TiGü ( 7. Mai 2014 um 13:06 Uhr)
  Mit Zitat antworten Zitat