2010-04-01 47 views
4

基於一個答案到一個較早的post,我調查了以下設計的可能性,現在德爾福:RTTI和TObjectList <TObject>

TChildClass = class(TObject) 
private 
    FField1: string; 
    FField2: string; 
end; 

TMyClass = class(TObject) 
private 
    FField1: TChildClass; 
    FField2: TObjectList<TChildClass>; 
end; 

,在現實世界中,TMyClass都會有這樣10名不同的列表,所以我希望能夠使用RTTI來解決這些列表。但是,我對這個類的其他領域不感興趣,所以我需要檢查某個字段是否是某種TObjectList。這是我到目前爲止:

procedure InitializeClass(RContext: TRttiContext; AObject: TObject); 
var 
    ROwnerType: TRttiType; 
    RObjListType: TRttiType; 
    RField:  TRttiField; 
    SchInf:  TSchemaInfoDetail; 
begin 
ROwnerType := RContext.GetType(AObject.ClassInfo); 
RObjListType := RContext.GetType(TObjectList<TObject>); 
for RField in ROwnerType.GetFields do begin 
    // How do I check if the type of TMyClass.FField2 (which is TObjectList<TChildClass>) is some sort of TObjectList? 
end; 

顯然,RField.FieldType <> RObjListType.FieldType。但是,他們確實有一些關係,不是嗎?看起來很可怕(也是錯誤的),以便對通用功能進行非常詳細的檢查,以使極有可能RField.FieldType實際上是TObjectList

說實話,我對泛型非常不舒服,所以這個問題可能很幼稚。不過,我非常樂意學習。上述解決方案是否可能實施? TIA!

+0

謝謝梅森。我認爲將此標記爲2010年的問題有點矯枉過正。 – conciliator 2010-04-01 19:15:37

回答

5

每個泛型實例都是唯一的,並且與其他實例在RTTI方面沒有關係。因爲Delphi不能在運行時實例化泛型,所以沒有與.NET的GetGenericTypeDefinition。你可以做的最好的是看看這個類型的形狀 - 例如它實現GetEnumeratorAdd

這也可能是足夠的靈活性來處理一般集合類型,而不僅僅是那些從TObjectList<T>實例化。 C#中有類似的功能,其集合初始化 - 它尋找一個Add方法和插入調用它:

http://msdn.microsoft.com/en-us/library/bb384062.aspx

+0

謝謝巴里!我想我會在你指出的時候尋找一個Add-method。 +1 :) – conciliator 2010-04-01 11:07:19

1

德爾福可以在運行時實例化泛型類型。 問題是,通用類型通常不會保留在運行時信息中。如果你持有一個特定類型的全局變量(TObjectList < TChildClass>在你的情況下),在初始化部分實例化(並釋放)它,該特定類的運行時信息不會被鏈接器剝離,你將能夠實例化它稍後動態。 (你需要提供context.findType()類的完整限定名稱才能正常工作。) 我花了一些時間弄清楚如何做到這一點,我絕對不滿意它,但由於我沒有發現另一種方式,我現在必須處理它。如果有人知道更好的方式讓我知道。