Indirection sur les membres d'une classe en vb.net ou c#, indirection on class members in vb.net or c#

Soyez le premier à donner votre avis sur cette source.

Snippet vu 6 347 fois - Téléchargée 19 fois

Contenu du snippet

Bonjour,

Ayant fait un peu de Windev, la fonction la plus pratique de ce langage est que l'on peut faire de l'indirection sur n'importe quelle variable, c'est à dire y accéder en lecture et en écriture en construisant son nom dans une chaîne de caractère. C'est quelque chose qui n'est pas proposé en standard dans le FrameWork .NET et nombreux sont ceux qui se sont arrachés les cheveux en essayant de faire de l'indirection en .NET, car il faut avouer que c'est bien pratique lorsqu'on en a besoin. Le Framework .NET propose bien quelque chose pour les System.Windows.Forms, la propriété Controls. Mais c'est limité aux Form et ça ne permet surtout pas d'accéder aux membres ajoutés dans notre classe héritée de Form. "Me.Controls" n'est pas assez, il faudrait un "Me.Members".

Ma source propose donc une alternative qui fonctionne pour les membres de toutes les classes.

Qu'est ce que l'indirection, concrètement ?

C'est très simple :

Imaginez que vous avez 150 membres dans votre classe, nommés Membre1, Membre2, Membre3, ..., Membre150. Bon bien entendu une telle classe souffrirait d'un sérieux problème de conception, mais c'est juste pour l'exemple.
Imaginez ensuite que vous désiriez assigner une valeur à ces 150 membres. C'est fastidieux de le faire à la main...

On écrira donc :

Membre1 = 10
Membre2 = 10
Membre3 = 10
...
Membre150 = 10

Vous pouvez imaginer que c'est très long et très ennuyeux.
Que diriez vous de faire à la place :

Dim i as Integer
For i = 1 To 150
IndirectionSet(Me, Me.GetType(), "Membre" & i, 10)
Next

Et voilà, plus que 4 lignes de code !
La même chose pour l'accès en lecture :

Dim i as Integer
For i = 1 To 150
MsgBox( Indirection(Me, Me.GetType(), "Membre" & i) )
Next

Je pense que vous commencez à comprendre l'intérêt de la courte source que je vais vous proposer. Voyez plutôt le code. J'ai utilisé l'espace de nom System.Reflection pour arriver à mes fins. Il suffit donc d'importer System.Reflection puis de copier et coller ces deux procédures dans votre classe.

Source / Exemple :


' Au début de votre classe, n'oubliez pas d'importer cet espace de nom
Imports System.Reflection

Public Class MaClasse

    Public Membre1 As Integer
    Public Membre2 As Integer
    Public Membre3 As Integer
    ' et on ajoute jusqu'à 150...
    Public Membre150 As Integer

    Public Sub New()

        Dim i As Integer
        For i = 1 To 150
            'On assigne la valeur de chaque membre à la valeur 10
            IndirectionSet(Me, Me.GetType(), "Membre" & i, 10)

            'On affiche la valeur de chaque membre
            MsgBox( DirectCast(Indirection(Me, Me.GetType(), "Membre" & i), Integer) )
        Next

    End Sub

    ''' <summary>
    ''' Permet de récupérer la valeur du membre "membername" de l'objet "obj" de type "objtype"
    ''' </summary>
    ''' <param name="obj">Objet parent du membre dont on souhaite récupérer la valeur</param>
    ''' <param name="objtype">Type de l'objet parent</param>
    ''' <param name="membername">Nom du membre</param>
    ''' <returns>La valeur du membre spécifié. Si le membre n'est pas trouvé, une exception est levée.</returns>
    ''' <remarks></remarks>
    Private Function Indirection(ByRef obj As Object, ByVal objtype As Type, ByVal membername As String) As Object

        Dim fi As FieldInfo
        fi = objtype.GetField(membername)
        Return fi.GetValue(obj)

    End Function

    ''' <summary>
    ''' Permet d'assigner une valeur "value" au membre "membername" de l'objet "obj" de type "objtype"
    ''' </summary>
    ''' <param name="obj">Objet parent du membre à assigner</param>
    ''' <param name="objtype">Type de l'objet parent</param>
    ''' <param name="membername">Nom du membre</param>
    ''' <param name="value">Valeur du membre</param>
    ''' <remarks></remarks>
    Private Sub IndirectionSet(ByRef obj As Object, ByVal objtype As Type, ByVal membername As String, ByRef value As Object)

        Dim fi As FieldInfo
        fi = objtype.GetField(membername)
        fi.SetValue(obj, value)

    End Sub

End Class

Conclusion :


Ma petite source permettra à ceux qui désirent accéder aux membres d'un objet par leur nom et permet non seulement un gain de temps mais aussi un gain en visibilité. Le code est beaucoup plus court !

A voir également

Ajouter un commentaire

Commentaires

oommeeggaa3d
Messages postés
98
Date d'inscription
dimanche 24 avril 2005
Statut
Membre
Dernière intervention
3 septembre 2010
-
C'est simple et efficace. mais surtout tu m'apprends un truc, et comment l'exploiter.
bouv
Messages postés
1429
Date d'inscription
mercredi 6 août 2003
Statut
Membre
Dernière intervention
3 mars 2019
-
Bon exemple, mais un peu plus simple d'appel en utilisant une propriété :

Public Property Membre(ByVal Index As Integer) As Integer
Get
Dim oType As Type = Me.GetType
Dim FI As FieldInfo = oType.GetField("Membre" & Index.ToString)
Return FI.GetValue(Me)
End Get
Set(ByVal value As Integer)
Dim oType As Type = Me.GetType
Dim FI As FieldInfo = oType.GetField("Membre" & Index.ToString)
FI.SetValue(Me, value)
End Set
End Property

On utilise ensuite :

Membre(i) = 10
MsgBox Membre(i)
cs_Patrice99
Messages postés
1222
Date d'inscription
jeudi 23 août 2001
Statut
Membre
Dernière intervention
9 septembre 2018
-
L'exemple que tu as donné peut être remplacé par un tableau. Peut-tu donner un autre exemple ? (peut être pour faire du scripting, mais dans ce cas, il vaudrait mieux un moteur de script ? franchement je ne voie pas l'intérêt de la chose, et je me demande si ce n'est pas simplement une mauvaise habitude importée de Windev ?)
bouv
Messages postés
1429
Date d'inscription
mercredi 6 août 2003
Statut
Membre
Dernière intervention
3 mars 2019
-
Patrice99>>Effectivement l'exemple présenté peux être remplacé par un tableau puisque toutes les valeurs renvoyées sont du même type. Mais on pourrait très bien renvoyer des données ou objets de type différent.
Exemple, je suis en train de developper un logiciel de BDD avec les tables suivantes LEVEL1, LEVEL2... LEVEL5. Les tables possèdent des champs identiques et des champs différents. J'ai donc codé une classe pour chacune d'elle (cLevel1... cLevel5). Pas de tableau possible car les objets sont de type différent. Pour savoir à quelle classe accéder, je dois à chaque dois utiliser un Select Case 'Integer'. Ce genre de code me permettrait de m'en passer.
cs_Patrice99
Messages postés
1222
Date d'inscription
jeudi 23 août 2001
Statut
Membre
Dernière intervention
9 septembre 2018
-
Hum : LEVEL1 à LEVEL5 : là aussi d'autres personnes auraient peut être résolut le problème de manière différente : en factorisant une table commune, puis en créant des liens pour les tables contenant d'autres champs, avec au final pas de champ en commun, donc pas besoin d'indirection (mais une BDD plus complexe quand même). Je sais qu'il doit exister des cas où l'indirection peut servir, mais à mon avis, ce n'est pas fréquent, et c'est plus une question d'habitude de programmation à mon avis.

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.