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;

EDIT: Here is a specific simple implementation using a tDictionary from Generics.Collections to handle the registry storage...I'll leave extracting this into 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 was giving this some thought last night, and discovered another technique that you can merge into this concept. Interfaces. Here is a quick do nothing example, but can easily be extended:

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 would have to implement the QueryInterface, _AddRef and _Release methods and extend the interface to do something more useful.

于 2009-11-03T18:28:12.713 回答
5

The new RTTI unit in Delphi 2010 has a way of retrieving types declared in the interface section of units. For any given type, represented by a TRttiType instance, the TRttiType.QualifiedName property returns a name that can be used with TRttiContext.FindType later to retrieve the type. The qualified name is the full unit name (including namespaces, if they exist), followed by a '.', followed by the full type name (including outer types if it nested).

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

But this mechanism can't be used to retrieve instantiations of generic types that weren't instantiated at compile time; instantiation at runtime requires runtime code generation.

于 2009-11-04T01:06:02.853 回答
0

If you forget generics and basic types, the "RegisterClass" function would be helpful. But it doesn't work for generics or basic types.

于 2009-11-03T18:58:02.473 回答