Delphi:如何以编程方式创建泛型类型?

Lud*_*c C 3 delphi generics dynamic rtti

如何在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;
Run Code Online (Sandbox Code Playgroud)

如何动态构建此泛型类型?

一个限制,我不能使用

function GetInterfaced<T> : TRttiType
begin
    Result := TrttiContext.Create.GetType(TypeInfo(IMyInterface<T>))
end;
Run Code Online (Sandbox Code Playgroud)

编辑

我正在尝试使用Stefan的Spring4d容器创建一个类型来解析组件

例如 :

function ResolveLookup(aModelType : PTypeInfo) : TObject
var aLookupType : PTypeInfo
begin
    aLookupType := SomehowGetTypeOf(ILookup<aModelType>);
    Result := FContainer.Resolve(aLookupType).AsObject;     
end;
Run Code Online (Sandbox Code Playgroud)

我真正的用例是我定义了一组模型(

TAssociate = class(TModel)
TUser = class(TModel)
TMandate = class(TModel)
Run Code Online (Sandbox Code Playgroud)

我还为他们定义了"查找"视图:

TAssociateLookup = class(TForm, ILookupView<TAssociate>);
Run Code Online (Sandbox Code Playgroud)

我在容器中注册了它们

FContainer.RegisterType<TAssociateLookup, ILookupView<TAssociate>>);
Run Code Online (Sandbox Code Playgroud)

然后我定义了一个服务

function TLookupService.GetLookupFor(aModelTypeInfo : PTypeInfo) : IInterface
begin
    Result := FContainer.Resolve(SomeHowGetTypeOf(ILookupView<aModelTypeInfo>).AsInterface;
end
Run Code Online (Sandbox Code Playgroud)

问题是我不能使用TLookupService.GetLookupFor<T>,但我必须使用TLookupService.GetLookupFor(aTypeInfo : TTypeInfo)

这是因为接口不能具有通用成员.

如果我定义一个服务接口,我得到一个编译错误

ILookupService = interface
   GetLookupFor<T> : ILookupView<T>; // compilation error
end;
Run Code Online (Sandbox Code Playgroud)

所以我必须在这里移动泛型参数

ILookupService<T> = interface
   GetLookup : ILookupView<T>; 
end;
Run Code Online (Sandbox Code Playgroud)

但这意味着我必须为我想要使用的每种类型的查找都有一个ILookupService实例:

MyForm = class(TForm)

fAssociateLookupService : ILookupService<TAssociate>;
fMandateLookupService : ILookupService<TMandate>;
fTaskLookupService : ILookupService<TTask>

end;
Run Code Online (Sandbox Code Playgroud)

代替

MyForm = class(TForm)
   fLookupService: ILookupService;
end;
Run Code Online (Sandbox Code Playgroud)

这就是我想要定义这样的界面的原因

ILookupService = interface
   GetLookupFor(aType : PTypeInfo) : IInterface; 
end;
Run Code Online (Sandbox Code Playgroud)

所以我可以使用

procedure TMyForm.DoIt
var
  aLookup : ILookupView<TMandate>;
begin
    aLookup := fLookupService.GetLookupFor(TypeInfo(TMandate)) as ILookupView<TMandate>;
end;
Run Code Online (Sandbox Code Playgroud)

小智 9

我不认为T可以是动态的,编译器需要知道T在编译时的类型.

编译器为每种使用的T类创建一个泛型类.例如:

IMyInterface<TObjectType1>
IMyInterface<TObjectType2>
Run Code Online (Sandbox Code Playgroud)

它不会在运行时创建它们,它们是在编译时创建的.