2010-09-09 6 views
0

Ok, je ne pense pas que ce soit possible, donc j'ai pensé que je demanderais à être sûr. Je suis en train de créer une fonction qui reflète sur les propriétés d'une classe et les ajoute à cette structure de données que j'ai. Certaines propriétés sont des types génériques.cast à type générique à l'exécution

Nous avons donc dire DataType(Of T) qui a une propriété .Value de type T:

Dim properties = GetType(MyType).GetFields(Reflection.BindingFlags.Public Or _ 
              Reflection.BindingFlags.Instance) 
For Each prop As fieldinfo In properties 
    Collection.Add(prop.Name,prop.GetValue(poco)) 
Next 

Dans le collection.Add pour les types primitifs (Integer, String, etc. & hellip;) Je veux juste ajouter le type .. mais dans le cas de générique, je veux ajouter le DataType(Of T).Value. J'espère qu'il y a un peu de travail mais je ne pense pas qu'il y ait un moyen parce que le type de T ne peut pas être déterminé au moment de la compilation, n'est-ce pas? Idéalement, DirectCast(prop.getvalue(poco), DataType(Of T)).Value serait possible. C'est à ce moment-là que vous avez espéré que plus de dynamique apparaisse que ce qui est dans .NET 4.0.

+0

Donc je suppose que ce n'est pas possible? – coding4fun

+0

Votre réponse est ici: http://stackoverflow.com/questions/2891797/typecasting-generic-parameters – pylover

Répondre

1

Il me vient à l'esprit que j'ai peut-être mal lu votre question. Donc une autre réponse de ma part.

Vous pouvez éviter la nécessité de jeter à un type générique (où vous ne connaissez pas le paramètre de type) lors de l'exécution par l'introduction d'une nouvelle interface qui permet d'accéder à une propriété Value:

Public Interface IHasValue 
    Public ReadOnly Property Value As Object 
End Interface 

Ensuite, assurez-vous que votre classe DataType(Of T) implémente cette interface. Cela signifie que chaque objet DataType(Of T) (peu importe quel type de béton T est) est également un IHasValue, et vous serez en mesure de vérifier cela avec TypeOf(…) Is IHasValue:

Public Class DataType(Of T) : Implements IHasValue 

    Public Value As T 

    Public ReadOnly Property UntypedValue As Object Implements IHasValue.Value 
     Get 
      Return Me.Value 
     End Get 
    End Property 

End Class 

(Cette duplication de Value est nécessaire pour deux raisons: Tout d'abord il faut quand DataType(Of T).Value est un champ au lieu d'une propriété, et deuxièmement parce qu'ils ne disposent pas du même type.)

Alors, où vous remplissez votre collection avec des champs, vous pouvez vérifier si un champ particulier est un DataType(Of T) (et si oui, déballez le Value) procédez comme suit:

Dim value As Object = prop.GetValue(poco) 

If TypeOf(value) Is IHasValue Then   ' <- is value a DataType(Of T) ? ' 
    value = CType(value, IHasValue).Value ' <- if so, unwrap the value  ' 
End If 

Collection.Add(prop.Name, value) 

Ceci est probablement plus ce que vous êtes après que mon autre réponse, mais laissez-moi souligner ceci:

If TypeOf(…) Is … Then … est une odeur de code. Peut-être devriez-vous repenser votre code et étudier des solutions impliquant le polymorphisme.

+0

merci beaucoup stakx pour l'aide. Excellente solution Ya la meilleure solution serait de retourner un Basic Type appelez simplement BasicType et renvoyez-le plutôt que de taper T. BasicType tiendrait simplement le type T mais vous n'auriez pas à vous soucier de lancer dans ce cas. Malheureusement, cela nécessiterait beaucoup de revoir le code parce que cette chose est utilisée partout et très peu de gens ont utilisé l'interface. En tout cas merci beaucoup pour l'aide – coding4fun

0

D'abord, mes hypothèses sur ce que vous essayez de faire:

  1. Vous avez un objet nommé poco, ayant le type MyType.

  2. MyType a des champs de différents types, donc vous pensez que vous avez besoin de génériques.

  3. Vous avez une collection paire-valeur-clé nommée Collection, ayant probablement le type Dictionary(Of String, Object)? Vous souhaitez transférer tous les champs de poco (ie, leurs noms et valeurs) à Collection.


noeud latéral: Vous confondez les champs avec des propriétés: Votre code fonctionne sur les champs (en invoquant GetFields), alors que le texte de votre question parle des propriétés. Ce n'est pas la même chose!


En second lieu, quelques faits fondamentaux sur les collections et le système de type statique:

  • collections non typées (où les éléments sont du type Object) peut stocker toutes sortes de valeurs il.

  • collections typées (où les éléments sont d'un type plus spécifique, par exemple T) ne peut stocker des valeurs ayant le type T ou d'un type dérivé de la T.


Troisièmement, conclusions tirées de ce qui précède:

  • Dans votre cas, Collection doit être une collection typées, si elle est en effet vrai que poco (ayant le type MyType) a des champs de types différents. Les génériques ne vous aideront pas du tout dans ce cas, car ce n'est pas ce que les génériques sont destinés. Les génériques sont utiles lorsque vous souhaitez définir les opérations (c'est-à-dire les méthodes, le comportement) qui fonctionnent de la même manière, quel que soit le type d'objet sur lequel ils travaillent.

    Par exemple, List(Of T) définit un type de collection qui fonctionne de la même manière quel que soit le type T. Mais cela ne signifie pas que vous pouvez mettre quelque chose dans un List(Of T), car dès que vous instancier ce type — par exemple. avec Dim xs As New List(Of String) —, T sera fixée à un type spécifique — String —, et vous vous retrouvez avec une collection typée qui n'accepte que ce type de valeurs. Donc, encore une fois: Si vous avez besoin d'une collection qui stocke différents types d'objets, choisissez Object comme type de valeur plutôt que d'essayer de trouver une solution impliquant des génériques.


Cela étant dit, il y a une autre solution : polymorphisme.

Si vous voulez que votre code pour gérer les valeurs différemment, en fonction de leur type, le polymorphisme est la voie à suivre:

  • D'abord, vous définissez une interface ou une classe de base abstraite (par exemple DataType, bien que je Je vous suggère fortement de choisir un nom plus explicite!) qui spécifie ce qui peut être fait avec vos valeurs.

  • Deuxièmement, tapez Collection en tant que Dictionary(Of String, DataType). Cela signifie que seuls les objets de type DataType ou tout ce qui en dérive peuvent entrer dans la collection. Troisièmement, dériver de/implémenter DataType pour spécifier le comportement pour un type particulier.

Il ya un bon slide show called Conditionals and Polymorphism qui peut être d'intérêt ici.


Side note: Last but not least, vous pouveztrouver le type d'un paramètre de type générique: TypeOf(T).

Questions connexes