我编写了一个接受类类型(T)和接口类型(I)的函数,并将一个接口(I)返回给对象(T).这是代码.
- 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实现(其中类没有实现接口但QueryInterface返回它),我会在类上使用Supports调用:
- 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"',GUIDToString(GetTypeData(TypeInfo(I))^.GUID)]
- );
- AObject := T.Create;
- Supports(AObject,Result);
- end;