2011-10-14 15 views
3

鍵可以繼承的接口被用作TDictionary的關鍵?使用繼承的接口在TDictionary

//! Note the inheritance of the interfaces 
ILoggingProvider = interface 
    procedure Log(AMessage : string); 
end; 

IHTTPLoggingProvider = interface(ILoggingProvider)  
    function Login(AUserName : string; APassword : string) : boolean 
end; 

ILiveLoggingProvider = interface(ILoggingProvider) 
    function ConnectMonitor : boolean 
end; 

var 
    loggers : TDictionary<ILoggingProvider,TObject>; 

... 

loggers.add(ILoggingProvider, TSomeLogger.Create()); 
loggers.add(IHTTPLoggingProvider , TSuperLogger.Create()); //fails! 
loggers.add(ILiveLoggingProvider , TAnotherLogger.Create()); //fails! 


... //and the use them selectively 

if loggers.ContainsKey(IHTTPLoggingProvider) then 
    loggers.Items[IHTTPLoggingProvider].Log('Good bye world!'); 

... //and like this 

var 

    theLogger : IHTTPLoggingProvider; 

if loggers.ContainsKey(IHTTPLoggingProvider) then 
begin 
    theLogger := IHTTPLoggingProvider(loggers.Items[IHTTPLoggingProvider]); 
    if theLogger.Login('billy', 'bones') then 
    theLogger.Log('some message'); 
end; 
+0

當然'TDictionary '希望接口引用,而不是接口。而'TObject'到'IHTTPLoggingProvider'的轉換非常可疑。值類型應該是一個接口。我想讓鑰匙成爲我想的GUID。或者我有沒有把握棒的錯誤結局? –

+0

@大衛:正確的 - 使用接口也將工作,並在使用純接口的做法更加一致的 - 不錯的主意。當我聲明'TLoggers = TDictionary '它提出了對結構的 'TLoggers' 實例的一個異常'無效類型cast'而'記錄程序:= TDictionary .Create'字細。有任何想法嗎? – MX4399

+0

我的答案中的代碼編譯,運行並正確運行。 –

回答

3

繼從我的評論,這裏就是我想實現這一點的:

type 
    ILoggingProvider = interface 
    ['{30598F45-1230-4208-B1A5-E1D2DA8F6D40}'] 
    procedure Log(AMessage : string); 
    end; 

    IHTTPLoggingProvider = interface(ILoggingProvider) 
    ['{CFA01514-AC44-4E30-971B-115986B37D26}'] 
    function Login(AUserName : string; APassword : string) : boolean; 
    end; 

    ILiveLoggingProvider = interface(ILoggingProvider) 
    ['{6EA68BEF-8D78-4FDF-AACD-1D164A272758}'] 
    function ConnectMonitor : boolean; 
    end; 

    TLoggingProvider = class(TInterfacedObject, ILoggingProvider) 
    procedure Log(AMessage : string); 
    end; 

    THTTPLoggingProvider = class(TInterfacedObject, ILoggingProvider, IHTTPLoggingProvider) 
    procedure Log(AMessage : string); 
    function Login(AUserName : string; APassword : string) : boolean; 
    end; 

    TLiveLoggingProvider = class(TInterfacedObject, ILoggingProvider, ILiveLoggingProvider) 
    procedure Log(AMessage : string); 
    function ConnectMonitor : boolean; 
    end; 

procedure Main; 
var 
    loggers : TDictionary<TGUID,ILoggingProvider>; 
    theLogger : IHTTPLoggingProvider; 
begin 
    loggers := TDictionary<TGUID,ILoggingProvider>.Create; 
    try 
    loggers.add(ILoggingProvider, TLoggingProvider.Create); 
    loggers.add(IHTTPLoggingProvider, THTTPLoggingProvider.Create); 
    loggers.add(ILiveLoggingProvider, TLiveLoggingProvider.Create); 

    if loggers.ContainsKey(IHTTPLoggingProvider) then 
     loggers.Items[IHTTPLoggingProvider].Log('Good bye world!'); 

    if loggers.ContainsKey(IHTTPLoggingProvider) then 
    begin 
     theLogger := loggers.Items[IHTTPLoggingProvider] as IHTTPLoggingProvider; 
     if theLogger.Login('billy', 'bones') then 
     theLogger.Log('some message'); 
    end; 
    finally 
    loggers.Free; 
    end; 
end;