RTTI: can I get the type by name?

Given a text string containing the type name, is there a way to get the corresponding type?

I want to do something like this:

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

I looked through several RTTI explanations on the Internet and looked through Delphi modules and can't see what I'm looking for. Is it possible?

+4
source share
4 answers

No, generics are fully compiled.

+7
source

You can always register your types in some registry (controlled by a string list or a dictionary) and create a factory function to return the corresponding object. Unfortunately, you need to know in advance what types you will need. Something similar to the Delphi RegisterClass and FindClass functions (in the class block). My thinking is to directly enter the generic type of the template into the list.

Possible use example:

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

EDIT: Here is a specific simple implementation using tDictionary from Generics.Collections to handle registry storage ... I will leave this extraction in useful methods as a simple exercise for the reader.

 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; 

Another EDIT: I thought of this thought last night and discovered another technique that you can combine into this concept. Interfaces Here's a quick example of nothing, but it can be easily expanded:

 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; 

Of course, you will have to implement the QueryInterface, _AddRef and _Release methods and extend the interface to do something more useful.

+5
source

The new RTTI module in Delphi 2010 has a way to get the types declared in the block interface section. For any given type represented by an instance of TRttiType , the TRttiType property returns a name that can be used with TRttiContext.FindType later to get the type. Qualified name is the full name of the unit (including namespaces, if they exist), followed by ".", Followed by the full name of the type (including external types, if nested).

So, you can get a representation of type Integer (in the form of TRttiType ) with context.FindType('System.Integer') .

But this mechanism cannot be used to obtain instances of generic types that were not created at compile time; creating an instance at runtime requires the generation of a runtime code.

+5
source

If you forget the generics and basic types, the "RegisterClass" function will be useful. But this does not work for generics or base types.

0
source

All Articles