Einzelnen Beitrag anzeigen

jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#15

Re: Plugin-System mit Interfaces und DLLs

  Alt 23. Mär 2006, 20:41
Ich habe mir für ein Programm ein Klasse geschrieben, die erst auf die Interface-Referenzzählung "hört", wenn ich mittels einer eigenen Methode "Release" (unterschied zu _Release) als Freizugeben markiert habe. Damit kann ich das Objekt auch ohne Interface nutzen. Defekte Plugins zerschießen mir damit auch nicht das gesamte Programm.

Delphi-Quellcode:
type
  TInterfaceNeutralObject = class(TModifyObject)
  private
    FRefCount: Integer;
    FAllowRelease: Boolean;
  protected
    procedure CleanUp; virtual; // hier den Destruktorcode einfügen
  public
    destructor Destroy; override;
    function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;

    procedure Release; // Statt .Free muss Release aufgerufen werden
  end;

{ TInterfaceNeutralObject }

function TInterfaceNeutralObject.QueryInterface(const IID: TGUID; out Obj): HRESULT;
begin
  if GetInterface(IID, Obj) then
    Result := 0
  else
    Result := E_NOINTERFACE;
end;

procedure TInterfaceNeutralObject.Release;
begin
  if (FRefCount = 0) and not FAllowRelease then
  begin
    CleanUp;
    FAllowRelease := True;
    Free;
  end
  else
  begin
    CleanUp;
    FAllowRelease := True;
    if FRefCount = 0 then
      Free;
  end;
end;

procedure TInterfaceNeutralObject.CleanUp;
begin
end;

function TInterfaceNeutralObject._AddRef: Integer;
begin
  Result := -1;
  Inc(FRefCount);
end;

function TInterfaceNeutralObject._Release: Integer;
begin
  Result := -1;
  Dec(FRefCount);
  if (FRefCount <= 0) and FAllowRelease then
    Free;
end;

destructor TInterfaceNeutralObject.Destroy;
begin
  {$IFDEF INTFDEBUG}
  if not FAllowRelease then
    //raise Exception.CreateFmt('InterfaceNeutralObject "%s" was not destroyed by Release', [ClassName]);
    MessageBox(0, PChar(Format('InterfaceNeutralObject "%s" was not destroyed by Release', [ClassName])), 'Error', MB_ICONHAND or MB_OK);
  {$ENDIF INTFDEBUG}
  inherited Destroy;
end;
Aber wenn man es richtig macht, dann sollte man besser ein weiteres Interface deklarieren, dass dann den Zugriff auf die "versteckten" Eigenschaften erlaubt. Dem Plugin-System muss man dieses Interface ja nicht verraten. Alternativ kann man auch eine GetObject: TObject Methode dem Interface hinzufügen, dass dann das dahinterliegende Objekt zurückliefert.
  Mit Zitat antworten Zitat