我得到像'TGroupBox'或'TEdit'數據庫中的字符串...現在我需要檢查元素對他們...我怎麼枚舉字符串鍵入?德爾福 - 如何枚舉字符串來鍵入
我的意思是這樣的:
mystr := 'TGroupBox';
If (page.Controls[0] is mystr) then ...
當然它不會工作,因爲出現錯誤:
E2015操作並不適用於這一運算對象類型
如何我做得對嗎?
我得到像'TGroupBox'或'TEdit'數據庫中的字符串...現在我需要檢查元素對他們...我怎麼枚舉字符串鍵入?德爾福 - 如何枚舉字符串來鍵入
我的意思是這樣的:
mystr := 'TGroupBox';
If (page.Controls[0] is mystr) then ...
當然它不會工作,因爲出現錯誤:
E2015操作並不適用於這一運算對象類型
如何我做得對嗎?
您可以驗證使用ClassName
財產
page.Controls[0].ClassName = mystr
。
但請注意,這不會完成與is
運算符完全相同的操作。要看到不同之處,假設您有一個類TFruit
和一個子類TApple
。如果myFruit
是TApple
的實例,則myFruit is TApple
和myFruit is TFruit
將產生true
。但是,當然,ClassName
仍然只是TApple
。
如果需要is
運營商的全部功能,您可以通過HVD利用ClassParent
財產,爲suggested:
function IsDerivedFrom(AClass: TClass; const AClassName: string): boolean;
begin
if not Assigned(AClass) then Exit(false);
result := SameText(AClass.ClassName, AClassName) or
IsDerivedFrom(AClass.ClassParent, AClassName);
end;
要獲得類的對象,請使用ClassType
屬性:
IsDerivedFrom(page.Controls[0].ClassType, mystr);
對於問題主體中的具體情況,Andreas Rejbrand(在hvd的協助下)的回答是一個很好的答案。但是,對於問題標題所隱含的更廣泛的問題 - 如何將包含類名的字符串轉換爲類引用? - 你可以在Delphi中的一個新的(ISH)版本使用擴展RTTI:
unit ClassLookupUtils;
interface
uses
System.SysUtils, System.Generics.Collections, System.Rtti;
type
RttiClassLookup = record
strict private
class var FMap: TDictionary<string, TClass>;
class destructor Destroy;
public
class function Find(const ClassName: string): TClass; static;
end;
implementation
class destructor RttiClassLookup.Destroy;
begin
FMap.Free;
end;
class function RttiClassLookup.Find(const ClassName: string): TClass;
var
RttiType: TRttiType;
RttiContext: TRttiContext;
begin
if FMap = nil then
begin
FMap := TDictionary<string, TClass>.Create;
for RttiType in RttiContext.GetTypes do
if RttiType is TRttiInstanceType then
FMap.AddOrSetValue(RttiType.Name.ToLowerInvariant, (RttiType as TRttiInstanceType).MetaclassType);
end;
if not FMap.TryGetValue(ClassName.ToLowerInvariant, Result) then
Result := nil;
end;
end.
在使用中:
var
MyStr: string;
MyStrClass: TClass;
begin
//...
MyStrClass := RttiClassLookup.Find(MyStr);
if MyStrClass <> nil then
for I := 0 to Page.ControlCount - 1 do
if Page.Controls[I].InheritsFrom(MyStrClass) then
begin
//...
end;
這裏的背景是SomeObj is SomeClass
作爲(SomeObj <> nil) and SomeObj.InheritsFrom(SomeClass)
實施。
RTTI讓你創建自己的字典?哎喲。偉大的代碼,我認爲這確實回答了原來的問題。 – alcalde
TRttiContext有一個FindType方法,但需要傳遞給它的完全限定名(例如'Vcl.StdCtrls.TGroupBox'),並且OP希望使用非限定名。 –
您正在尋找的功能是位於System.Classes中的GetClass
。請注意,班級必須註冊。
你必須從@UweRaabe使用RTTI
獲得ClassName
一個很好的答案。
一個簡單的(不是很強大的)hack而不使用RTTI就是使用TComponent。Name屬性,它是一個字符串,像這樣 - 沒有is
操作:
If (pos('GroupBox', page.Controls[0].name)>0) then ...
默認情況下,控制得到了相同的名稱作爲實例變量,所以GroupBox1.name='GroupBox1
」。您可以更改數據庫條目以使用substr'groupbox'或從數據庫中的類型名稱字符串中提取'groupbox'。這就是說,如果您繼承了這種設計方法,即將類型名稱作爲字符串保存在數據庫中,然後在運行時使用它們來檢查不同組件的類型,那麼您就會被卡住,所以它。但是Delphi是一種強類型的編譯語言,因此將類型名稱作爲數據庫中的字符串持久存儲,並在運行時讀取它們並將它們解碼爲Delphi類型並不會「正確地識別」IMO。如果可能的話,我會重新考慮這個設計。考慮在Delphi中使用classOf
類型,枚舉等來完成所有操作。
你究竟在做什麼? –
我實際上試圖做我所問的。爲了能夠在'string'上使用'is'運算符。所以我想最好的方法是將這個'string'轉換爲'class' ......但不知道如何。 –
你不能用is來表示一個字符串,所以如果這就是你想要做的,放棄 –