Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Interface nur unter bestimmten Bedingungen unterstützen (https://www.delphipraxis.net/185629-interface-nur-unter-bestimmten-bedingungen-unterstuetzen.html)

Muzel 25. Jun 2015 14:34

Interface nur unter bestimmten Bedingungen unterstützen
 
Gibt es eine Möglichkeit, ein Interface nur unter bestimmten Bedingungen zu unterstützen?
Ich habe es folgendermaßen versucht:
- das Interface mit seinen Methoden in meiner Klasse implementiert
- QueryInterface in der Klasse überschrieben:

function MyClass.QueryInterface (const IID: TGUID; out Obj): HResult;
begin
if IsEqualGUID (IID, ITheInterface) then
begin
// hier könnte ich meine Bedingungen prüfen
Result := E_NOINTERFACE;
Pointer(Obj) := nil;
end
else
Result := inherited QueryInterface (IID, Obj);
end;

Was ich nicht verstehe: Obwohl bei der Supports-Abfrage der Code durchlaufen wird (also E_NOINTERFACE) zurückkommt, gibt Support True zurück und das Obj ist nicht nil.

Uwe Raabe 25. Jun 2015 14:50

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Das solltest du nicht tun, denn damit verletzt du eine Regel für Interfaces:

Zitat:

The set of interfaces accessible on an object through QueryInterface must be static, not dynamic. This means that if a call to QueryInterface for a pointer to a specified interface succeeds the first time, it must succeed again, and if it fails the first time, it must fail on all subsequent queries.
IUnknown::QueryInterface method

Mavarik 25. Jun 2015 15:08

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Was willst Du den damit erreichen?

Der schöne Günther 25. Jun 2015 15:15

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Vielleicht hat er Ideen wie eine Klasse die mit irgendetwas kommuniziert. Dazu ein Interface
Delphi-Quellcode:
IDingsKommunikator
. Wenn allerdings der Stecker draußen ist, kann es nicht kommunizieren. Und unterstützt das Interface nicht.

Solche Ideen hatte ich auch mal. Stellte sich aber wirklich als Schnapsidee heraus.

Uwe Raabe 25. Jun 2015 15:19

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Ein Problem sehe ich darin, wenn sich jemand das Interface holt wenn es gerade unterstützt wird, sich der Zustand aber dann so ändert, daß es nicht mehr unterstützt wird. Das Interface bleibt dann weiterhin gültig und es werden immer noch die entsprechenden Methoden aufgerufen. Also muss man die Bedingung dann immer noch prüfen und hat nichts gewonnen.

Besser dem Interface eine zusätzliche Funktion spendieren (z.B. IsValid), die sagt, ob man es gerade benutzen darf.

Mikkey 25. Jun 2015 16:49

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1306622)
Besser dem Interface eine zusätzliche Funktion spendieren (z.B. IsValid), die sagt, ob man es gerade benutzen darf.

Und eine
Delphi-Quellcode:
InvalidOperationException
, die von den betreffenden Schnittstellenfunktionen geworfen wird.

Muzel 26. Jun 2015 07:10

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Ok, danke, ihr habt mich überzeugt.
aber ich wüsste schon gern, warum sich die Supports-Funktion so seltsam verhält.

Der schöne Günther 26. Jun 2015 09:23

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Kannst du mal deinen vollständigen Quelltext posten? Welches
Delphi-Quellcode:
QueryInterface
wird denn zur Laufzeit benutzt? Ich denke mal, du hast vergessen, in deiner Klassendefinition
Delphi-Quellcode:
IInterface
anzugeben, oder?+

Hier mal ein Beispiel:
Delphi-Quellcode:
program SupportsProject;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

type
   IMyInterface = interface
   ['{03A20C4F-400C-462F-B10D-D19B01E82919}']
      procedure testProcedure();
   end;

   TMyClass = class(TInterfacedObject, (*IInterface, *)IMyInterface)
      protected var
         shouldSupport: Boolean;
      public
         constructor Create(const shouldSupport: Boolean = True);
         procedure testProcedure();

         function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
   end;

procedure justSupportThings();
var
   instance:      IInterface;
   myIntf:         IMyInterface;
   shouldSupport:   Boolean;
begin
   shouldSupport := False; // Hier anpassen

   instance := TMyClass.Create(shouldSupport);
   if Supports(instance, IMyInterface, myIntf) then begin
      WriteLn('Instance supports interface');
      myIntf.testProcedure();
   end else
      WriteLn('Instance does not support interface');
end;

{ TMyClass }

procedure TMyClass.testProcedure();
begin
   WriteLn('This is the test procedure');
end;

constructor TMyClass.Create(const shouldSupport: Boolean);
begin
   inherited Create();
   self.shouldSupport := shouldSupport;
end;

function TMyClass.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
   if (not shouldSupport) then Exit(E_NOINTERFACE) else Result := inherited;
end;

begin
  try
   justSupportThings();
  except
    on E: Exception do
     Writeln(E.ClassName, ': ', E.Message);
  end;
  readln;
end.

Muzel 2. Jul 2015 10:05

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Mein Code ist im Wesentlichen so wie in dem Beispiel. IInterface ist in der Vorgängerklasse schon drin, deshalb macht es keinen Unterschied, wenn ich es nochmal angebe.

Der schöne Günther 2. Jul 2015 15:47

AW: Interface nur unter bestimmten Bedingungen unterstützen
 
Zitat:

Zitat von Muzel (Beitrag 1307451)
deshalb macht es keinen Unterschied

Nö.


Alle Zeitangaben in WEZ +1. Es ist jetzt 18:44 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz