Is there a non-reference-counted base class like TInterfacedObject?

前端 未结 5 1269
无人及你
无人及你 2021-02-07 08:47

I need a base class like TInterfacedObject but without reference counting (so a kind of TNonRefCountedInterfacedObject).

This actually is the

相关标签:
5条回答
  • 2021-02-07 09:16

    In the unit Generics.Defaults there is a class TSingletonImplementation defined. Available in Delphi 2009 and above.

      // A non-reference-counted IInterface implementation.
      TSingletonImplementation = class(TObject, IInterface)
      protected
        function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
      end;
    
    0 讨论(0)
  • 2021-02-07 09:23

    I did this. It can be used in place of TInterfacedObject with or without reference counting. It also has a name property - very useful when debugging.

    // TArtInterfacedObject
    // =============================================================================
    
    
    // An object that supports interfaces, allowing naming and optional reference counting
    type
      TArtInterfacedObject = class( TInterfacedObject )
        constructor Create( AReferenceCounted : boolean = True);
      PRIVATE
        FName             : string;
        FReferenceCounted : boolean;
      PROTECTED
        procedure SetName( const AName : string ); virtual;
      PUBLIC
    
        property Name : string
                   read FName
                   write SetName;
    
        function QueryInterface(const AGUID : TGUID; out Obj): HResult; stdcall;
        function SupportsInterface( const AGUID : TGUID ) : boolean;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
    
      end;
    
    // =============================================================================
    
    
    
    
    { TArtInterfacedObject }
    
    constructor TArtInterfacedObject.Create( AReferenceCounted : boolean = True);
    begin
      inherited Create;
    
      FName := '';
    
      FReferenceCounted := AReferenceCounted;
    end;
    
    function TArtInterfacedObject.QueryInterface(const AGUID: TGUID; out Obj): HResult;
    const
      E_NOINTERFACE = HResult($80004002);
    begin
      If FReferenceCounted then
        Result := inherited QueryInterface( AGUID, Obj )
       else
        if GetInterface(AGUID, Obj) then Result := 0 else Result := E_NOINTERFACE;
    end;
    
    
    procedure TArtInterfacedObject.SetName(const AName: string);
    begin
      FName := AName;
    end;
    
    function TArtInterfacedObject.SupportsInterface(
      const AGUID: TGUID): boolean;
    var
      P : TObject;
    begin
      Result := QueryInterface( AGUID, P ) = S_OK;
    end;
    
    
    function TArtInterfacedObject._AddRef: Integer;
    begin
      If FReferenceCounted then
        Result := inherited _AddRef
       else
        Result := -1   // -1 indicates no reference counting is taking place
    end;
    
    function TArtInterfacedObject._Release: Integer;
    begin
      If FReferenceCounted then
        Result := inherited _Release
       else
        Result := -1   // -1 indicates no reference counting is taking place
    end;
    
    
    // =============================================================================
    
    0 讨论(0)
  • 2021-02-07 09:25

    There is no such class, but you can easily write your own, as others have shown. I do, however, wonder why you would need it. In my experience, there is seldom a real need for such a class, even if you want to mix object and interface references.

    Also note that when you use such a class, you'll still have to take care of setting any interface references you have to such an object to nil before they leave scope and before you free the object. Otherwise you might get the situation the runtime tries to call _Release on a freed object, and that tends to cause an invalid pointer exception.

    IOW, I would advise against using such a class at all.

    0 讨论(0)
  • 2021-02-07 09:27

    You might consider TInterfacedPersistent. If you don't override GetOwner it does no ref-counting.

    0 讨论(0)
  • 2021-02-07 09:27

    I don't know of any out-of-the-box base class, so I wrote my own (like you). Just put it in a common utils unit and you are done.

    type
      TPureInterfacedObject = class(TObject, IInterface)
      protected
        { IInterface }
        function QueryInterface(const IID: TGUID; out Obj): HResult; virtual; stdcall;
        function _AddRef: Integer; stdcall;
        function _Release: Integer; stdcall;
      end;
    
    { TPureInterfacedObject }
    
    function TPureInterfacedObject.QueryInterface(const IID: TGUID; out Obj): HResult;
    begin
      Result := E_NOINTERFACE;
    end;
    
    function TPureInterfacedObject._AddRef: Integer;
    begin
      Result := -1;
    end;
    
    function TPureInterfacedObject._Release: Integer;
    begin
      Result := -1;
    end;
    
    0 讨论(0)
提交回复
热议问题