2016-04-20 14 views
2

Wie kann ich einen generischen Typ in Delphi dynamisch erstellen?Delphi: Wie man einen generischen Typ programmatisch erzeugt?

mich

Lassen Sie erklären Wenn ich eine Schnittstelle IMyInterface<T>, haben

Ich möchte die allgemeine T Parameter dynamisch zuweisen und einen Verweis auf diese Art irgendwie zu bekommen.

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; 

Wie kann ich diesen generischen Typ dynamisch erstellen?

Eine Einschränkung, ich darf nicht verwenden

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

bearbeiten

ich eine Art zu schaffen, ich versuche, eine Komponente mit Stefans Spring4d Behälter

Zum Beispiel zu beheben:

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

habe ich wirklich hier Anwendungsfall ist, dass ich eine Menge von Modellen definiert haben (

TAssociate = class(TModel) 
TUser = class(TModel) 
TMandate = class(TModel) 

I definiert "Lookup" Ansichten für sie auch:

TAssociateLookup = class(TForm, ILookupView<TAssociate>); 

ich sie als

im Container registriert
FContainer.RegisterType<TAssociateLookup, ILookupView<TAssociate>>); 

I definiert dann einen Dienst

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

Das Problem ist, dass ich nicht TLookupService.GetLookupFor<T> verwenden können, aber ich TLookupService.GetLookupFor(aTypeInfo : TTypeInfo)

Dies ist aufgrund der Tatsache, dass Schnittstellen nicht generisch Mitglieder können verwenden.

Wenn ich eine Service-Schnittstelle zu definieren, wie so erhalte ich einen Übersetzungsfehler

ILookupService = interface 
    GetLookupFor<T> : ILookupView<T>; // compilation error 
end; 

Also muss ich den generischen Parameter bewegen hier

ILookupService<T> = interface 
    GetLookup : ILookupView<T>; 
end; 

Das bedeutet aber, dass ich eine Instanz der haben muss ILookupService für jeden Suchtyp, den ich verwenden möchte:

MyForm = class(TForm) 

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

end; 

anstelle von

MyForm = class(TForm) 
    fLookupService: ILookupService; 
end; 

diesem Grund habe ich eine Schnittstelle wie so

ILookupService = interface 
    GetLookupFor(aType : PTypeInfo) : IInterface; 
end; 

So konnte ich

procedure TMyForm.DoIt 
var 
    aLookup : ILookupView<TMandate>; 
begin 
    aLookup := fLookupService.GetLookupFor(TypeInfo(TMandate)) as ILookupView<TMandate>; 
end; 
+3

Können Sie ein Beispiel dafür geben, wie Sie eine solche Funktion verwenden würden, wenn es möglich wäre, sie zu implementieren? –

+1

Dies kann nicht in Delphi getan werden. Aber ich denke, Sie sind hier auf etwas anderes, d. H. Sie versuchen, etwas mit dem TRTtiType zu tun, den Sie anfordern - was ist das? –

+0

Siehe Bearbeiten. – Ludo

Antwort

8

ich die T dynamisch sein kann, Der Compiler nicht denken verwenden definieren wollte muss wissen, welcher Typ T zur Kompilierzeit ist.

Der Compiler erstellt eine generische Klasse für jeden Typ von T verwendet. Zum Beispiel:

IMyInterface<TObjectType1> 
IMyInterface<TObjectType2> 

sie diese während der Laufzeit nicht schaffen, werden sie bei der Kompilierung erstellt.