我需要一个基类,类似于TInterfacedObject
,但不包含引用计数(类似于TNonRefCountedInterfacedObject
)。
实际上这已经是我第n次需要这样一个类了,但我总是不断地重新编写我的代码(即复制并粘贴)。我无法相信没有官方的基类可供使用。
在RTL中是否有一个实现了IInterface
接口但没有引用计数的基类,我可以从中派生我的类?
我需要一个基类,类似于TInterfacedObject
,但不包含引用计数(类似于TNonRefCountedInterfacedObject
)。
实际上这已经是我第n次需要这样一个类了,但我总是不断地重新编写我的代码(即复制并粘贴)。我无法相信没有官方的基类可供使用。
在RTL中是否有一个实现了IInterface
接口但没有引用计数的基类,我可以从中派生我的类?
在单位Generics.Defaults中定义了一个名为TSingletonImplementation的类。该类在Delphi 2009及以上版本中可用。
// 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;
我做了这个。 它可以代替TInterfacedObject,带或不带引用计数。 它还有一个名字属性——在调试时非常有用。
// 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;
// =============================================================================
E_NOINTERFACE
而责备你。但我刚刚注意到 VCL 定义了它四次,所以你只是一个轻微的罪犯。:-P - Uli Gerhardt我不知道有任何现成的基类,所以我自己写了一个(就像你一样)。只需将其放入公共 utils 单元中,你就完成了。
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;
TInterfacedPersistent.QueryInterface
中复制实现。 - Uli Gerhardt虽然没有这样的类,但是你可以像其他人一样轻松地编写自己的类。然而,我想知道为什么你需要它。在我的经验中,即使你想混合对象和接口引用,也很少真正需要这样的类。
另外请注意,当你使用这样的类时,你仍然需要在离开作用域之前将任何接口引用设置为 nil,并在释放对象之前进行清理。否则,你可能会遇到运行时试图在已释放的对象上调用 _Release 的情况,这往往会导致无效指针异常。
换句话说,我建议不要使用这样的类。
TComponent
会禁用引用计数,但你可能不想携带TComponent
中的所有东西。我不知道是否有任何预定义的类,我写了自己的类。 - jpfolleniusTComponent
,但还是决定先问一下问题;) 我想使用一个小的、专用的类。 - Heinrich UlbrichtTInterfacedPersistent
对我来说仍然太重了,我差点使用TPureInterfacedObject
(我喜欢这个名字!),但是@Erwin介绍了纯本地实现!尽管我不喜欢TSingletonImplementation
这个名字。 - Heinrich UlbrichtTNonRefCountedInterfacedObject = TSingletonImplementation
,以免混淆自己。 - stanleyxu2005