質問
DelphiでオブジェクトをXMLに解析しようとしています。そのため、オブジェクトのClassInfoメソッドを呼び出してRTTI情報を取得する方法を読みました。
問題は、明らかにTPersistentオブジェクトに対してのみ機能することです。そうでない場合は、RTTI情報を生成するためにコンパイラのソースコードにコンパイラディレクティブ{$ M +}を具体的に追加する必要があります。
したがって、幸いにもディレクティブを追加しましたが、ClassInfo呼び出しから何かを返した場合でも(nilを返していた)、クラスのプロパティ、フィールド、またはメソッドを取得できません。空のオブジェクトを作成したようなものです。
ここで何が欠けているのでしょうか?ありがとう!
解決
これらのプロパティとメソッドを published
セクションに入れましたか?
それ以外に、「クラシック」RTTI($ TYPEINFO ON)は、メソッドではなくプロパティに関する情報のみを取得します。それらには「拡張」RTTI($ METHODINFO ON)が必要です。
拡張RTTIの良い出発点: David Glassborow拡張RTTIで
(この1分で拡張RTTIを使用するコードの記述を完了し、少しスタックオーバーフローを参照することにしたと信じている人)
他のヒント
RTTIは、公開済みプロパティなどのみを表示します。 -パブリックなものだけではありません。
TObjectを使用してコードを試して、何が起こるかを確認します。それが機能しない場合は、誰もが心霊的ではないため、コードを投稿してください。
TXMLDocumentコンポーネントの使用を検討しましたか? XMLを見て、XMLファイルを表すDelphiクラスの素敵なユニットを作成します。XMLファイルの読み書きが本当に簡単になります。
nttiのみを返すRttiTypeの問題に関しては、これはおそらく1つの理由で発生する可能性があります。テストでは、いつでもクラスをインスタンス化しなかったためです。コンパイラーは、このクラスへの参照を一切持たないため(まったくインスタンスではないため)、最適化の形式として情報から単純に削除します。以下の2つの例を参照してください。コードのある時点でクラスをインスタンス化した場合とそうでない場合の動作は異なります。
次のクラスを想定します:
type
TTest = class
public
procedure Test;
end;
および以下のコード:
var
LContext: TRttiContext;
LType: TRttiType;
LTest: TTest;
begin
LContext := TRttiContext.Create;
for LType in LContext.GetTypes do
begin
if LType.IsInstance then
begin
WriteLn(LType.Name);
end;
end;
end;
これまでのところ、TTestクラス情報はRTTIで使用できません。ただし、アプリケーション内のある時点で作成すると、コンパイル内で参照が作成され、この情報が利用可能になります。
var
LContext: TRttiContext;
LType: TRttiType;
LTest: TTest;
begin
LTest := TTest.Create; //Here i´m using TTest.
//Could be in another part of the program
LContext := TRttiContext.Create;
for LType in LContext.GetTypes do
begin
if LType.IsInstance then
begin
WriteLn(LType.Name);
end;
end;
end;
その時点で LContext.FindType( 'TTest')を使用すると、コンパイラはクラスへの参照を保持するため、nilが返されません。これは、テストでの動作を説明しています。