4

以前の投稿への 1 つの回答に基づいて、次の設計の可能性を調査しています。

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.FieldTypeTObjectList.

正直なところ、私はジェネリックにはかなり慣れていないので、質問は非常にナイーブかもしれません. しかし、私は学ぶことが何よりもうれしいです。上記の解決策を実装することは可能ですか? ティア!

4

2 に答える 2

6

すべての一般的なインスタンス化は一意であり、RTTIに関して他のインスタンス化とは関係がありません。Delphiは実行時にジェネリック型をインスタンス化できないため、たとえば.NETに相当するものはありませんGetGenericTypeDefinition。あなたができる最善のことは、タイプの形を調べることです-例えば、それは実装しますGetEnumeratorAdd

これは、からインスタンス化されたものだけでなく、一般的なコレクションタイプを処理するのに十分な柔軟性もありますTObjectList<T>。C#は、コレクション初期化子と同様のことを行います。メソッドを探し、そのAddメソッドへの呼び出しを挿入します。

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

于 2010-04-01T10:18:58.793 に答える
2

Delphi は、実行時にジェネリック型をインスタンス化できます。問題は、一般的にジェネリック型がランタイム情報に保持されないことです。特定の型 (この場合は TObjectList< TChildClass >) のグローバル var を保持している場合は、初期化セクションでインスタンス化 (および解放) します。その特定のクラスの実行時情報はリンカーによって取り除かれず、インスタンス化できるようになります。後で動的に。(context.findType() が適切に機能するためには、クラスの完全修飾名を指定する必要があります。) これを行う方法を理解するのに時間を費やしましたが、満足していません。今のところ、別の方法で対処する必要があります。誰かがより良い方法を知っているなら、私に知らせてください。

于 2010-12-11T15:24:40.433 に答える