2009-11-03 78 views
4

给定一个包含类型名称的文本字符串,是否有某种方法可以获得适当的类型本身?RTTI:我可以通过名称获取类型吗?

我希望做这样的事情:

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

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

我在几个RTTI解释在网上看了,看着通过德尔福单位并没有看到什么我要找的。这可能吗?

+0

你希望你能用你创建的对象做什么样的“东西”? – 2009-11-03 17:08:38

+0

从中获取一个接口。它是持久性方案的一部分。 – TrespassersW 2009-11-03 17:48:15

+0

谁说它有一个可以“抓取”的界面?如果你对这个类型有足够的了解,知道它实现了一个特定的接口,那么你就足够了解不需要去做你上面的代码片断了。 – 2009-11-03 18:42:43

回答

7

不,泛型完全是编译时。

+0

那么,crud。看起来你是对的。这笔投资创造了一个非常酷的想法。谢谢(你的)信息。 – TrespassersW 2009-11-03 17:58:54

+0

尽管如此,仍然有好奇的是,如果有一种方法可以从名称中获取类型。即使我不能完全按照我想要的方式使用它。 – TrespassersW 2009-11-03 17:59:47

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方法和扩展接口做更有用的东西。

+0

谢谢你。这正是我一直在做的事情(很久以前从Delphi的TPersistent中获得了这个想法)。你的建议是我们已经提出的(注册每个模板类型),并且工作正常。我希望有更灵活和动态的东西,但看起来并不像我想要的那样。再次感谢。 – TrespassersW 2009-11-03 20:55:01

+0

这可以很容易做到灵活和动态。你不能做的唯一事情就是你没有计划的句柄类型。 – skamradt 2009-11-03 21:45:23

0

如果您忘记了泛型和基本类型,那么“RegisterClass”函数将会有所帮助。但它不适用于泛型或基本类型。

5

Delphi 2010中的新RTTI单元有一种检索单元接口部分声明的类型的方法。对于任何给定类型(由TRttiType实例表示),TRttiType.QualifiedName属性将返回一个名称,该名称可以稍后用于TRttiContext.FindType以检索该类型。限定名称是完整的单元名称(包括名称空间,如果存在的话),后跟一个'。',后跟完整类型名称(如果嵌套,则包括外部类型)。

因此,您可以用context.FindType('System.Integer')检索Integer类型的表示形式(形式为TRttiType)。

但是,这种机制不能用于检索在编译时未实例化的泛型类型的实例;运行时实例化需要运行时代码生成。

+0

太棒了!谢谢(你的)信息。 – TrespassersW 2009-11-04 16:33:51

相关问题