Delphi:를 구현하는 방법의 응용 프로그램을 실 IUnknown?
-
26-09-2020 - |
문제
델파이, IUnknown
으로 선언:
function QueryInterface(const IID: TGUID; out Obj): HResult; stdcall;
참고: 출력 매개 변수가 형식화되지 않은
나 TInterfacedObject
하위 난 필요가 처리 QueryInterface
, 다,그래서 나는 반환할 수 있는 객체 지원 요청된 인터페이스::
function TFoo.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if IsEqualGUID(IID, IFooBar) then
begin
Obj := (TFooBar.Create(Self) as IFooBar);
Result := S_OK;
end
else
Result := inherited QueryInterface(IID, {out}Obj);
end;
문제는 온 라인:
Obj := (TFooBar.Create(Self) as IFooBar);
델파이 불평:
운영자는 적용되지 않습 이 연산자 종류
분명히 내가 알지 못에 어떻게 또는 무엇을 할당할 턴 out
매개 변수입니다.수은 무작위로도 일,희망에 있는 컴파일러를 중지 불평:
Obj := TFooBar.Create(Self);
Obj := Pointer(TFooBar.Create(Self));
Obj := Pointer(TFooBar.Create(Self) as IFooBar);
을 무시하고 모든 코드를 작성(필요한 경우):를 구현하는 방법 QueryInterface
에는 개체의 후손 TInterfacedObject
?
진짜 문제를 해결할 수 있습으로 아래로 삶은 내가 원하는:
내가 원하는 재정의하는 방법에는 인터페이스
에서 동일한 방법:
TList = class(TObject)
...
function GetItem(Index: Integer): Pointer;
procedure SetItem(Index: Integer; Value: Pointer);
property Items[Index: Integer]: Pointer read GetItem write SetItem;
end;
될 수 있습에 하위 클래스:
TStudentList = class(TList)
...
function GetItem(Index: Integer): TStudent;
procedure SetItem(Index: Integer; Value: TStudent);
property Items[Index: Integer]: TStudent read GetItem write SetItem;
end;
내가 원하도록 동일한 인터페이스:
IFoo = interface(IUnknown)
...
function GetItem(Index: Variant): Variant;
procedure SetItem(Index: Variant; Value: Variant);
property Items[Index: Variant]: Variant read GetItem write SetItem;
end;
IFooGuidString = interface(IFoo)
...
function GetItem(Index: TGUID): string ;
procedure SetItem(Index: TGUID; Value: string );
property Items[Index: TGUID]: string read GetItem write SetItem;
end;
문제는 어떻게 시작할 수 있을 로드하는 내 구현하는 객체:
TFoo = class(TInterfacedObject, IFoo, IFooGuidString)
public
function IFoo.GetItem = FooGetItem;
procedure IFoo.SetItem = FooSetItem;
function FooGetItem(Index: Variant): Variant;
procedure FooSetItem(Index: Variant; Value: Variant);
function IFooGuidString.GetItem = FooGuidStringGetItem;
procedure IFooGuidString.SetItem = FooGuidStringSetItem;
function FooGuidStringGetItem(Index: TGUID): string ;
procedure FooGuidStringSetItem(Index: TGUID; Value: string );
end;
고 있지 않은 단지 두 가지 방법에 IFoo
, 가 6.다음하고 싶은 경우에 다른 추가 지원하는 인터페이스::
IFooInt64String = interface(IFoo)
...
function GetItem(Index: Int64): string ;
procedure SetItem(Index: Int64; Value: string );
property Items[Index: Int64]: string read GetItem write SetItem;
end;
TFoo = class(TInterfacedObject, IFoo, IFooGuidString)
public
function IFoo.GetItem = FooGetItem;
procedure IFoo.SetItem = FooSetItem;
function FooGetItem(Index: Variant): Variant;
procedure FooSetItem(Index: Variant; Value: Variant);
function IFooGuidString.GetItem = FooGuidStringGetItem;
procedure IFooGuidString.SetItem = FooGuidStringSetItem;
function FooGuidStringGetItem(Index: TGUID): string ;
procedure FooGuidStringSetItem(Index: TGUID; Value: string );
function IFooInt64String.GetItem = FooInt64StringGetItem;
procedure IFooInt64String.SetItem = FooInt64StringSetItem;
function FooInt64StringGetItem(Index: Int64): string ;
procedure FooInt64StringSetItem(Index: Int64; Value: string );
end;
고 일을 정말로 다루기 힘든 매우 빠르다.
해결책
을 입력 할 필요가-캐스팅 남 측정의 문입니다.는 방법,형식화되지 않은 매개변수 유형,컴파일러는 방법을 알고 있는 값을 할당합니다:
IFooBar(Obj) := TFooBar.Create(Self) as IFooBar;
참고는 당신이 중 하나를 깨뜨리 의 요구 사항 COM.는 경우 쿼리를 위한 인터페이스,당신이 할 수 있어야한 쿼리에 대한 결과 IUnknown 과 항상 같은 값을 얻:
Foo.QueryInterface(IUnknown, I1);
I1.QueryInterface(IFooBar, B);
B.QueryInterface(IUnknown, I2);
Assert(I1 = I2);
하려면 새로 생성 개체를 유형의 TFooBar,다음을 제공하는 인터페이스 방법을 생성하는 사람들:
function TFoo.NewFooBar: IFooBar;
begin
Result := TFooBar.Create(Self) as IFooBar;
end;
다른 팁
외의 강탈의 발언의 규칙을 여기에서,당신은 수도 성공과 함께 이를 구성:
function TFoo.QueryInterface(const IID: TGUID; out Obj): HResult;
begin
if IsEqualGUID(IID, IFooBar) then
Result := TFooBar.Create(Self).QueryInterface(IID, obj)
else
Result := inherited QueryInterface(IID, {out}Obj);
end;
내가 이것을 조사하지 않았지만,당신이 얻을 수 있습니다 몇몇 문제들을 참조 계산...
의 구현을 기반으로 TObject.GetInterface 에서는 시스템입니다.pas I would suggest this:
Pointer(Obj) := TFooBar.Create(Self);