2010-06-02 5 views
6

Son kullanıcı için belirli arabirim türlerinin listesini sunma amacıyla, bir dizi nesneden küçük arabirimleri tek bir TInterfaceList 'store' içine saklıyorum. Arabirim bir 'GetName' işlevini gösterecektir, ancak diğer tüm yöntemler bu arabirim türüne özgüdür. Örneğin burada iki arayüzleri:Bir Delphi içinde birden çok arabirim türü saklamak ve bulmak için TInterfaceList

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

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

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

Ben tek TInterfaceList içine bu ara yüzlerin birkaç koyun ve sonra ben (örneğin 'IMeasureTemperature') işaretçileri başka bir liste bina belirli bir arabirim türü için listeyi taramak istiyorum Bu arayüzleri ihraç eden nesnelere. Bu nesnelerin yerleri hakkında herhangi bir varsayım yapmak istemiyorum, bazıları birden fazla arayüz türünü ihraç edebilir.

If FList[I] is TMeasureTemperature then .. 

ancak bir arayüz türüyle simliar bir şey yapmak istiyorum, bu mümkün mü: Ben gibi bir şey kullanarak bir sınıf hiyerarşisi ile bu yapabileceğini biliyor musunuz? (Eğer unitialized bellek bunları deneyin sürece) onlar oldukça güvenlidir,

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

İlk listenizde bu arabirimleri uygulayan gerçek arabirim * türleri * veya object * örneklerine * başvurular olup olmadığını açıklığa kavuşturmak isteyebilirsiniz. Bu soruya cevap verirken, şimdiye kadar bu soruya cevap verenlerin hepsi, eskiden bahsetmek için sorunuzu okurken ... o zaman yine bir "TInterfaceList" içinde * tipini * saklayamaz gibi görünüyor. ... –

cevap

2

Ben senin ihtiyaçlarını karşılamak olabilir sanırım: arayüz türü yayın yapmak için çalışıyoruz.

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

Ben intf ve ExpectedIntf birbirinden devralan zaman fonksiyonu nasıl davranacağını emin değilim, ama bu intf ExpectedIntf tam bir eşleşme durumunda DOĞRU dönecektir.

Örnek olarak, IMeasureHumidity, IMeasureTemperature'da true olarak geri dönmeyecektir, ancak IBase'e nasıl tepki vereceğinden emin değilim. Ön testlere göre, aynı zamanda IBase üzerinde FALSE döndürecektir.

+0

'ExpectedIntf'' IUnknown' dışında, 'Int''nın vReferans’a eşit olacağını garanti etmez. [QueryInterface uygulamak için kurallar] (http://msdn.microsoft.com/en-us/library/ms686590.aspx) QueryInterface çağrısının başarılı olacağına dair söz verir, ancak belirli bir arabirim işaretçisinin döndürülmesini gerektirmez. –

+0

Kendi bağlantınızdan "IID_IUnknown ile QueryInterface çağrısı her zaman aynı fiziksel işaretçi değerini döndürmelidir" ve "Herhangi bir arabirim, bir nesnede başka bir arabirim için sorgulayabilmelidir". Hangi kuralı uyguladığınızı bilmiyorum, bu başarısız olur. –

+0

Bu iyi çalışıyor ve tam olarak ne beklediğimi yapıyor, ne yaptıklarını görmek için çok zor görünmem gerekiyordu! Devralınan IBase arabiriminin geçirileceği bir durum asla olmaz. Çok teşekkürler. –

6

Bunun gibi, desteler kullanmak


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: Güzel bir öneri ancak tek bir sınıf iki farklı arabirimi dışa aktardığında başarısız olur - 'Destekler' bu durumda her biri için doğru döner. Arayüzün gerçek tipini tanımlamanın bir yoluna ihtiyacım var. –

+0

Üzgünüz, anahtar noktanızı kaçırdım. Arabirimden nesneyi almanız veya arayüzden arayüz almanız mı gerekiyor? İlk önce, http://www.malcolmgroves.com/blog/?p=500. İkinciyse, yazdığım gibi (mesajımı düzenledim). –

+0

@Brian: Neden bu bir sorun? İki arabirimden biri diğerinden inerse, ana sınıftan önceki alt sınıfı kontrol edin. Ve eğer yapmazlarsa, o zaman her iki sonuç da eşit derecede geçerlidir. –

2

Sen SysUtils içinde Supports işlevini kullanabilir ve yalnızca tam bir hedef değişkeni gerekir: