4

型名を含むテキスト文字列が与えられた場合、適切な型自体を取得する方法はありますか?

私はこのようなことをしようとしています:

type
  TSomeType<T> = class
    // yadda yadda
  end;

procedure DoSomething;
var
  obj : TObject;
begin
  o := TSomeType<GetTypeByName('integer')>.Create;
  // do stuff with obj
end;

オンラインでいくつかの RTTI の説明を調べ、Delphi ユニットを調べましたが、探しているものがわかりません。これは可能ですか?

4

4 に答える 4

7

いいえ、ジェネリックは完全にコンパイル時です。

于 2009-11-03T16:57:03.427 に答える
5

いつでも何らかの種類のレジストリ (文字列リストまたは辞書によって管理される) に型を登録し、ファクトリ関数を作成して適切なオブジェクトを返すことができます。残念ながら、必要になるタイプを事前に知っておく必要があります。Delphi 関数の RegisterClass および FindClass に似たもの(クラス ユニット内)。私の考えは、一般的なテンプレートの型を直接リストに入れることです。

可能な使用例:

RegisterCustomType('Integer',TSomeType<Integer>);
RegisterCustomType('String',TSomeType<String>);

if FindCustomType('Integer') <> nil then
  O := FindCustomType('Integer').Create;

編集: Generics.Collections の tDictionary を使用してレジストリ ストレージを処理する特定の単純な実装を次に示します。読者の簡単な演習として、これを有用なメソッドに抽出したままにします。

var
  o : TObject;
begin
  TypeDict := TDictionary<String,TClass>.Create;
  TypeDict.Add('integer',TList<integer>);
  if TypeDict.ContainsKey('integer') then
    o := TypeDict.Items['integer'].Create;
  if Assigned(o) then
    ShowMessage(o.ClassName);
end;

別の編集:昨夜これについて考えていたところ、この概念に統合できる別の手法を発見しました。インターフェイス。何もしない簡単な例を次に示しますが、簡単に拡張できます。

TYPE
  ITest = interface
    ['{0DD03794-6713-47A0-BBE5-58F4719F494E}']
  end;

  TIntfList<t> = class(TList<T>,ITest)
  public
    function QueryInterface(const IID: TGUID; out Obj): HRESULT; stdcall;
    function _AddRef: Integer; stdcall;
    function _Release: Integer; stdcall;
  end;

procedure TForm1.Button7Click(Sender: TObject);
var
  o : TObject;
  fTestIntf : ITest;
begin
  TypeDict := TDictionary<String,TClass>.Create;
  TypeDict.Add('integer',TIntfList<integer>);
  if TypeDict.ContainsKey('integer') then
    o := TypeDict.Items['integer'].Create;
  if Assigned(o) and Supports(o,ITest,fTestIntf) then
    ShowMessage(o.ClassName);
end;

もちろん、QueryInterface、_AddRef、および _Release メソッドを実装し、インターフェイスを拡張して、より便利なことを行う必要があります。

于 2009-11-03T18:28:12.713 に答える
5

Delphi 2010 の新しい RTTI ユニットには、ユニットのインターフェイス セクションで宣言されたタイプを取得する方法があります。TRttiTypeインスタンスで表される特定の型について、プロパティは、後で型を取得するためにTRttiType.QualifiedName使用できる名前を返します。TRttiContext.FindType修飾名は、完全なユニット名 (存在する場合は名前空間を含む) であり、その後に '.' が続き、その後に完全な型名 (入れ子になっている場合は外部型を含む) が続きます。

TRttiTypeしたがって、 を使用して Integer 型の表現を ( a の形式で)取得できますcontext.FindType('System.Integer')

ただし、このメカニズムを使用して、コンパイル時にインスタンス化されなかったジェネリック型のインスタンス化を取得することはできません。実行時のインスタンス化には、実行時のコード生成が必要です。

于 2009-11-04T01:06:02.853 に答える
0

ジェネリックと基本型を忘れた場合は、「RegisterClass」関数が役立ちます。ただし、ジェネリックや基本型では機能しません。

于 2009-11-03T18:58:02.473 に答える