如何在Delphi中动态构建泛型类型?
让我解释一下
如果我有一个界面IMyInterface<T>
,
我想动态分配通用T
参数,并以某种方式获取对该类型的引用。
function GetInterfaced(aType : PTypeInfo) : TRttiType
begin
Result := ???
// I want to return TypeInfo(IMyInterface<aType>);
// or a RttiType that corresponds to TRttiContext.GetType(IMyInterface<aType>)
end;
如何动态构建此通用类型?
一个限制,我不得使用
function GetInterfaced<T> : TRttiType
begin
Result := TrttiContext.Create.GetType(TypeInfo(IMyInterface<T>))
end;
编辑
我正在尝试使用Stefan的Spring4d容器创建一个解析组件的类型
例如:
function ResolveLookup(aModelType : PTypeInfo) : TObject
var aLookupType : PTypeInfo
begin
aLookupType := SomehowGetTypeOf(ILookup<aModelType>);
Result := FContainer.Resolve(aLookupType).AsObject;
end;
我的真实用例是我定义了一组模型(
TAssociate = class(TModel)
TUser = class(TModel)
TMandate = class(TModel)
我还为他们定义了“查找”视图:
TAssociateLookup = class(TForm, ILookupView<TAssociate>);
我在容器中将它们注册为
FContainer.RegisterType<TAssociateLookup, ILookupView<TAssociate>>);
然后我定义了一个服务
function TLookupService.GetLookupFor(aModelTypeInfo : PTypeInfo) : IInterface
begin
Result := FContainer.Resolve(SomeHowGetTypeOf(ILookupView<aModelTypeInfo>).AsInterface;
end
问题在于我无法使用TLookupService.GetLookupFor<T>
,但我必须使用TLookupService.GetLookupFor(aTypeInfo : TTypeInfo)
这是因为接口不能包含通用成员。
如果我定义了一个服务接口,那么我会收到编译错误
ILookupService = interface
GetLookupFor<T> : ILookupView<T>; // compilation error
end;
所以我必须在这里移动通用参数
ILookupService<T> = interface
GetLookup : ILookupView<T>;
end;
但是这意味着我必须为我想要使用的每种类型的查找都有一个ILookupService实例:
MyForm = class(TForm)
fAssociateLookupService : ILookupService<TAssociate>;
fMandateLookupService : ILookupService<TMandate>;
fTaskLookupService : ILookupService<TTask>
end;
而不是
MyForm = class(TForm)
fLookupService: ILookupService;
end;
这就是为什么我想要定义一个像这样的界面
ILookupService = interface
GetLookupFor(aType : PTypeInfo) : IInterface;
end;
所以我可以使用
procedure TMyForm.DoIt
var
aLookup : ILookupView<TMandate>;
begin
aLookup := fLookupService.GetLookupFor(TypeInfo(TMandate)) as ILookupView<TMandate>;
end;
答案 0 :(得分:8)
我不认为T可以是动态的, 编译器需要知道T在编译时的类型。
编译器为每种使用的T类型创建一个泛型类。 例如:
IMyInterface<TObjectType1>
IMyInterface<TObjectType2>
它不会在运行时创建它们,它们是在编译时创建的。