Frage

Bei einer Textzeichenfolge einen Typnamen enthält, ist es eine Möglichkeit, die geeignete Art selbst zu bekommen?

Ich bin auf der Suche, so etwas zu tun:

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

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

Ich habe online auf mehrere RTTI Erklärungen schaute und schaute durch die Delphi-Einheiten und nicht sehen, was ich suche. Ist das möglich?

War es hilfreich?

Lösung

Nein, Generika sind ganz compiletime.

Andere Tipps

Die neue RTTI-Einheit in Delphi 2010 hat eine Art und Weise Arten von Abrufen im Interfaceabschnitt der Einheiten erklärt. Für jeden gegebenen Typ von einem TRttiType Instanz dargestellt, gibt die TRttiType.QualifiedName Eigenschaft einen Namen, der später mit TRttiContext.FindType verwendet werden können, um die Art abzurufen. Der qualifizierte Name ist der vollständige Einheit Name (einschließlich Namespaces, wenn sie vorhanden ist), gefolgt von einem ‚‘, durch den vollständigen Typnamen gefolgt (einschließlich Außentypen, wenn sie verschachtelt).

Also, Sie könnten eine Darstellung des Integer-Typs abrufen (in Form eines TRttiType) mit context.FindType('System.Integer').

Aber dieser Mechanismus nicht verwendet werden kann Instanziierungen generische Typen abzurufen, die nicht bei der Kompilierung instanziiert wurden; Instantiierung zur Laufzeit Laufzeitcodegenerierung erfordert.

Sie können jederzeit Ihre Arten in eine Art von Registry (verwaltet durch eine String-Liste oder Wörterbuch) registrieren und eine Fabrik-Funktion erstellen, um dann das entsprechende Objekt zurück. Leider würden Sie im Voraus wissen müssen, welche Arten Sie benötigen würden. Etwas ähnlich wie die Delphi-Funktionen Registerclass und Findclass (in der Klassen-Einheit). Mein Denken ist, direkt den generischen Template-Typen in die Liste zu setzen.

Ein Beispiel für eine mögliche Nutzung:

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

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

EDIT: Hier eine bestimmte einfache Implementierung ist ein TDictionary von Generics.Collections mit der Registrierung Speicher zu handhaben ... Ich lasse diese in nützliche Methoden als eine einfache Übung für den Leser zu extrahieren.

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;

Ein weiterer EDIT: Ich war dies einige Gedanken gestern Abend zu geben, und entdeckt eine andere Technik, die Sie in dieses Konzept verschmelzen können. Schnittstellen. Hier ist ein kurz nichts tut Beispiel, kann aber leicht erweitert werden:

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;

Natürlich würden Sie haben die Query-Interface, _AddRef und _Release Methoden implementieren und die Schnittstelle erweitern etwas Sinnvolles zu tun.

Wenn Sie Generika und Grundtypen vergessen, würde die „Register“ Funktion hilfreich sein. Aber es funktioniert nicht für Generika oder Grundtypen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top