4 Stimmen

.NET generische Klasseninstanz - Übergabe eines variablen Datentyps

Wie der Titel schon sagt, versuche ich, einen variablen Datentyp an eine Template-Klasse zu übergeben. Etwas wie dies:

frmExample = New LookupForm(Of Models.MyClass) 'Works fine

Dim SelectedType As Type = InstanceOfMyClass.GetType() 'Works fine
frmExample = New LookupForm(Of SelectedType) 'Ba-bow!
frmExample = New LookupForm(Of InstanceOfMyClass.GetType()) 'Ba-bow!

LookupForm<Models.MyClass> frmExample;
Type SelectedType = InstanceOfMyClass.GetType();
frmExample = new LookupForm<SelectedType.GetType()>(); //Ba-bow
frmExample = new LookupForm<(Type)SelectedType>(); //Ba-bow

Ich nehme an, es hat etwas mit der Vorlage zu tun, die zur Kompilierungszeit verarbeitet wird, aber selbst wenn ich dort falsch liege, würde das mein Problem nicht lösen. Ich kann auch keine relevanten Informationen über die Verwendung von Reflection zur Instanzierung von Vorlagenklassen finden.

(Wie) kann ich eine Instanz eines dynamisch typisierten Repositorys zur Laufzeit erstellen?

9voto

Matt Mitchell Punkte 39413

Ein C#-Beispiel, das dem sehr nahe kommt, finden Sie hier aquí auf eine Frage, die ich hatte:

typeof(MyClass).GetMethod("Foo").MakeGenericMethod(new[] { param.GetType() }).Invoke(null, new[] { param });

Konvertierung in VB.NET, Änderung auf Typerstellung statt Methodenaufruf und Verwendung Ihrer Beispielnamen für Sie:

Dim frmExample as LookupForm<Models.MyClass>;
Dim SelectedType as Type = InstanceOfMyClass.GetType();   
Dim GenericLookupType as Type = GetType(LookupForm(Of)).MakeGenericType(SelectedType)
frmExample = Activator.CreateInstance(GenericLookupType, new object(){})

(Ah aus irgendeinem Grund dachte ich, Sie wollten es in VB.NET, aber hier ist ein C# Beispiel)

LookupForm<Models.MyClass> frmExample;
Type SelectedType = InstanceOfMyClass.GetType();   
Type GenericLookupType = typeof(LookupForm<>).MakeGenericType(SelectedType);
frmExample = Activator.CreateInstance(GenericLookupType, new object[]{});

7voto

Igor Zevaka Punkte 71448

使用方法 Type.MakeGenericType .

Type modelType = typeof(Models.MyClass);
var repoType = typeof(LookupForm<>).MakeGenericType(new [] {modelType} );
//at this point repoType == typeof(LookupForm<Models.MyClass>);
var repo = Activator.CreateInstance(repoType );
//Ta-dah!!!

Und VB.NET-Version :)

    Dim modelType As Type = GetType(Models.MyClass)
    Dim repoType As Type = GetType(LookupForm(Of )).MakeGenericType(New Type() {modelType})
    'at this point repoType = GetType(LookupForm(of Models.MyClass))'
    Dim repo = Activator.CreateInstance(repoType)
    'Ta-dah!!!'

1voto

Tim Long Punkte 13230

Das klingt wie ein Kandidat für die Dynamic Language Runtime, den Typ "Dynamic" in C#, aber dafür müssten Sie .NET 4.0 verwenden.

1voto

Alconja Punkte 14686

Leider kann man dies nicht ohne Reflexion tun und selbst dann ist es nicht sehr freundlich. Die Reflexion Code wird etwas wie dieses aussieht:

Type baseType = typeof(LookupForm<>);
Type selectedType = InstanceOfMyClass.GetType(); //or however else you want to get hold of it
Type genericType = baseType.MakeGenericType(new Type[] { selectedType });
object o = Activator.CreateInstance(genericType);

Natürlich wissen Sie jetzt nicht, worauf Sie Ihr Objekt werfen sollen (vorausgesetzt selectedType dynamisch gesetzt wurde), aber Sie können immer noch die Methoden auf sie über Reflexion aufrufen, oder Sie könnten eine nicht-generische Schnittstelle erstellen, um es zu casten und die Methoden auf das aufrufen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X