使用泛型创建接口对象
Using Generics to create an interfaced object
我编写了一个函数,它接受 class 类型 (T) 和接口类型 (I) 以及 returns 对象 (T) 的接口 (I)。这是代码。
interface
function CreateObjectInterface<T: Class, constructor; I: IInterface>(
out AObject: TObject): I;
...
implementation
function TORM.CreateObjectInterface<T, I>(out AObject: TObject): I;
begin
AObject := T.Create;
if not Supports(AObject, GetTypeData(TypeInfo(I))^.Guid, Result) then
begin
AObject.Free;
AObject := nil;
raise EORMUnsupportedInterface.CreateFmt(
'Object class "%s" does not support interface "%s"',
[AObject.ClassName, GUIDToString(GetTypeData(TypeInfo(I))^.GUID)]
);
end;
end;
该函数按预期工作,没有内存泄漏或其他不良情况。
还有其他方法可以达到同样的效果吗?
此代码中存在错误。如果支持 IUnknown
但不支持您要求的接口,支持将销毁您的对象实例。
简单演示:
type
IFoo = interface
['{32D3BE83-61A0-4227-BA48-2376C29F5F54}']
end;
var
o: TObject;
i: IFoo;
begin
i := TORM.CreateObjectInterface<TInterfacedObject, IFoo>(o); // <- boom, invalid pointer
end.
最好将 IInterface
或 IUnknown
作为 T
的附加约束。
或者确保您没有销毁已经销毁的实例。
除非你想支持动态 QueryInterface
实现(其中 class 不实现接口但 QueryInterface
returns 它)我会选择 Supports
调用 class:
function TORM.CreateObjectInterface<T, I>(out AObject: TObject): I;
begin
if not Supports(TClass(T), GetTypeData(TypeInfo(I))^.Guid) then
raise EORMUnsupportedInterface.CreateFmt(
'Object class "%s" does not support interface "%s"',
[AObject.ClassName, GUIDToString(GetTypeData(TypeInfo(I))^.GUID)]
);
AObject := T.Create;
Supports(AObject, GetTypeData(TypeInfo(I))^.Guid, Result);
end;
我编写了一个函数,它接受 class 类型 (T) 和接口类型 (I) 以及 returns 对象 (T) 的接口 (I)。这是代码。
interface
function CreateObjectInterface<T: Class, constructor; I: IInterface>(
out AObject: TObject): I;
...
implementation
function TORM.CreateObjectInterface<T, I>(out AObject: TObject): I;
begin
AObject := T.Create;
if not Supports(AObject, GetTypeData(TypeInfo(I))^.Guid, Result) then
begin
AObject.Free;
AObject := nil;
raise EORMUnsupportedInterface.CreateFmt(
'Object class "%s" does not support interface "%s"',
[AObject.ClassName, GUIDToString(GetTypeData(TypeInfo(I))^.GUID)]
);
end;
end;
该函数按预期工作,没有内存泄漏或其他不良情况。
还有其他方法可以达到同样的效果吗?
此代码中存在错误。如果支持 IUnknown
但不支持您要求的接口,支持将销毁您的对象实例。
简单演示:
type
IFoo = interface
['{32D3BE83-61A0-4227-BA48-2376C29F5F54}']
end;
var
o: TObject;
i: IFoo;
begin
i := TORM.CreateObjectInterface<TInterfacedObject, IFoo>(o); // <- boom, invalid pointer
end.
最好将 IInterface
或 IUnknown
作为 T
的附加约束。
或者确保您没有销毁已经销毁的实例。
除非你想支持动态 QueryInterface
实现(其中 class 不实现接口但 QueryInterface
returns 它)我会选择 Supports
调用 class:
function TORM.CreateObjectInterface<T, I>(out AObject: TObject): I;
begin
if not Supports(TClass(T), GetTypeData(TypeInfo(I))^.Guid) then
raise EORMUnsupportedInterface.CreateFmt(
'Object class "%s" does not support interface "%s"',
[AObject.ClassName, GUIDToString(GetTypeData(TypeInfo(I))^.GUID)]
);
AObject := T.Create;
Supports(AObject, GetTypeData(TypeInfo(I))^.Guid, Result);
end;