2010-06-02 7 views
4

Comme le titre le suggère, je tente de transmettre un type de données variable à une classe modèle. Quelque chose comme ceci:Instance de classe générique .NET - Transmission d'un type de données variable

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 

Je suppose que c'est quelque chose à voir avec le modèle en cours de traitement au moment de la compilation, mais même si je suis loin du compte là, il ne résoudrait pas mon problème de toute façon. Je ne trouve pas non plus d'informations pertinentes sur l'utilisation de Reflection dans les classes de modèles d'instance.

(Comment) puis-je créer une instance d'un référentiel de type dynamique lors de l'exécution?

+1

Vous ne trouverez aucune information sur la création d'un modèle dynamique dans VB.NET ou C#, car aucune langue ne prend en charge les modèles. Ils soutiennent tous deux les génériques, qui sont sensiblement différents. –

+0

duplication possible de [Passer un système instancié.Type comme paramètre de type pour une classe générique] (http://stackoverflow.com/questions/266115/pass-an-instanced-system-type-as-a-type-parameter -for-a-generic-class) – usr

Répondre

9

exemple AC# quelque chose assez proche est situé here sur une question que j'avais:

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

Conversion en VB.NET, le changer à la création de type non invocation de la méthode et en utilisant vos noms d'exemple pour vous:

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 pour une raison quelconque, je croyais que tu voulais en VB.NET, mais voici un exemple C#)

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

Peut-être parce que le titre original avait VB.NET au début et la question avait seulement un exemple VB.NET :) J'ai supprimé la référence du titre et ajouté un C# espérant exploiter un plus grand état d'esprit. – nathanchere

+1

Merci pour l'acceptation. Vous découvrirez beaucoup de petits trous de lapin avec la plupart des applications de ce genre de choses, mais c'est un bon moyen de trouver des cas de limites d'une langue. –

1

Cela sonne comme un candidat pour le Dynamic Language Runtime, type 'dynamique' en C#, mais auriez-vous besoin d'utiliser .NET 4.0

+1

J'utilise .NET 4 – nathanchere

+0

Je pense que vous devriez encore utiliser Activator.CreateInstance mais vous pourriez faire mieux avec cela au moment de la compilation {ie LookupForm a = (LookupForm ) Activateur.CreateInstance (etc.); } et assurez-vous que SomeInstanceType correspond à d'autres types générés dynamiquement. C'est difficile à expliquer maintenant mais vous savez sans doute ce que je veux dire. –

6

Utilisez 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!!! 

et la version VB.NET :)

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!!!' 
1

Malheureusement vous ne pouvez pas faire cela sans réflexion et même alors ce ne est pas très sympathique. Le code de réflexion se ressemble à quelque chose comme ceci:

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); 

Bien sûr, maintenant vous ne savez pas quoi jeter votre objet (en supposant selectedType a été dynamiquement set), mais vous pouvez toujours appeler les méthodes sur elle par réflexion, ou vous pouvez créer une interface non générique pour la convertir en & appelez les méthodes sur cela.

+0

Il ne doit pas être amical dans la mise en œuvre tant que l'interface joue bien :) – nathanchere

Questions connexes