您始终可以将您的类型注册到某种注册表中(由字符串列表或字典管理)并创建一个工厂函数,然后返回适当的对象。不幸的是,您必须提前知道您需要什么类型。类似于 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 方法并扩展接口以做一些更有用的事情。