2010-06-02 5 views
6

특정 인터페이스 유형의 목록을 최종 사용자에게 제공하기 위해 여러 객체의 작은 인터페이스를 단일 TInterfaceList 'store'에 저장하므로 각 인터페이스는 'GetName'기능을 노출하지만 다른 모든 메소드는 해당 인터페이스 유형에 고유합니다. 예를 들어 여기에 두 개의 인터페이스는 다음과 같습니다Delphi TInterfaceList 내에 여러 인터페이스 유형을 저장하고 찾는 방법

IBase = interface 
    //---------------------------------------- 
    function GetName : string; 
    //---------------------------------------- 
    end; 

    IMeasureTemperature = interface(IBase) 
    //------------------------------------ 
    function MeasureTemperature : double; 
    //---------------------------------------- 
    end; 

    IMeasureHumidity = interface(IBase) 
    //---------------------------------------- 
    function MeasureHumidity: double; 
    //---------------------------------------- 
    end; 

나는 하나의 TInterfaceList으로 이러한 인터페이스의 몇 가지 넣고 I (예 : 'IMeasureTemperature') 포인터의 또 다른 목록을 구축하는 특정 인터페이스 유형에 대한 목록을 검색하고 싶습니다 해당 인터페이스를 내보내는 객체에 전달합니다. 이러한 객체의 위치에 대한 가정을하지 않으려 고하며, 일부 객체는 여러 유형의 인터페이스를 내보낼 수 있습니다.

If FList[I] is TMeasureTemperature then .. 

하지만 인터페이스 유형를 닮아 일을하고 싶습니다,이게 가능 : 나는 같은 것을 사용하여 클래스 계층이 할 수 알아? (당신이 초기화되지 메모리를 시도하지 않는 한) 그들은 꽤 안전,

var 
    oMTIntf: IMeasureTemperature; 
... 
    If Supports(FList[I], IMeasureTemperature, oMTIntf) then .. 
+1

첫 번째 목록에 실제 인터페이스 * 유형 * 또는 해당 인터페이스를 구현하는 객체 * 인스턴스 *에 대한 참조가 포함되어 있는지 여부를 명확히 할 수 있습니다. 이전에 대해 이야기하기 위해 질문을 읽는 동안 여기에 응답하는 모든 사람들이 후자를 가정 한 것처럼 보입니다 ... 다시 인터페이스 형식 *을'TInterfaceList'에 저장할 수 없으므로 아마도 틀렸을 것입니다 ... –

답변

2

그럴 수도 있습니다.

function InterfaceRefIsInterface(Intf : IUnknown; ExpectedIntf : TGUID) : Boolean; 
var vReference : IUnknown; 
begin 
    if Supports(Intf, ExpectedIntf, vReference) then 
    Result := Intf = vReference 
    else 
    Result := False; 
end; 

나는 Intf에와 ExpectedIntf가 서로 상속 할 때 기능이 동작하는 방법을 잘 모르겠지만,이 Intf에이 ExpectedIntf의 정확히 일치하는 경우에 TRUE를 반환합니다.

예제에서 IMeasureHumidity는 IMeasureTemperature에서 true를 반환하지 않지만 IBase에 어떻게 반응하는지 잘 모르겠습니다. 예비 테스트에 따르면 IBase에서도 FALSE를 반환합니다.

+0

'ExpectedIntf'가'IUnknown' 일 때를 제외하고'Intf'가'vReference'와 항상 동일하다는 보장은 없습니다. [QueryInterface 구현 규칙] (http://msdn.microsoft.com/en-us/library/ms686590.aspx)은 QueryInterface에 대한 호출이 성공할 것이라고 약속하지만 특정 인터페이스 포인터를 반환 할 필요가 없습니다. –

+0

자신의 링크에서 "IID_IUnknown이있는 QueryInterface 호출은 항상 동일한 실제 포인터 값을 반환해야합니다."및 "모든 인터페이스가 개체의 다른 인터페이스를 쿼리 할 수 ​​있어야합니다." 이 규칙을 위반하면 어떤 규칙을 참조 할 지 확신 할 수 없습니다. –

+0

이것은 잘 작동하고 정확히 무엇을 기대하고 있었는지, 비록 내가하고있는 일을보기 위해 열심히 조사 할 필요가 있겠지만! 계승 된 IBase 인터페이스가 전달되는 경우는 결코 없을 것입니다. 많은 감사. –

6

그냥이 같은 지원을 사용하여 전송하려는 인터페이스 유형 :


procedure DoSomethingInList(AList: IInterfaceList;); 
var 
    i: Integer; 
    liItem: IInterface; 
    liMeasureTemp: IMeasureTemperature; 
    liMeasureHumi: IMeasureHumidity; 
begin 
    AList.Lock; 
    try 
    for i := 0 to AList.Count - 1 do 
    begin 
     liItem := AList[i]; 
     if Supports(liItem, IMeasureTemperature, liMeasureTemp) then 
     //... liMeasureTemp.MeasureTemperature ... 
     else if Supports(liItem, IMeasureHumidity, liMeasureHumi) then 
     //... liMeasureHumi.MeasureHumidity ... 
     else 
     //... 
    end; 
    finally 
    AList.Unlock; 
    end; 
end; 
+0

@ da-soft : 좋은 제안이지만 단일 클래스가 두 개의 다른 인터페이스를 내보낼 때 실패합니다. 'Supports'는 각각에 대해 true를 반환합니다. 인터페이스의 실제 유형을 식별 할 수있는 방법이 필요합니다. –

+0

죄송합니다, 귀하의 핵심 포인트를 놓친 것 같습니다. 인터페이스에서 객체를 가져 오거나 인터페이스에서 인터페이스를 가져와야합니까? 처음이라면 http://www.malcolmgroves.com/blog/?p=500. 두 번째라면, 나는 (나는 나의 메시지를 편집했다.) 썼다. –

+0

@ 브라이언 : 왜 그게 문제 죠? 두 인터페이스 중 하나가 다른 인터페이스에서 내려온 경우 상위 클래스보다 하위 클래스를 확인하십시오. 그렇지 않은 경우 두 결과가 똑같이 유효합니다. –

2

당신은 SysUtils와의 Supports 기능을 사용할 수 있으며, 당신은 단지 정확한 목표 변수가 필요합니다

관련 문제