IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VB.NET Discussion :

System.Reflection SetValue dans un élément List(Of)


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Analyste programmeur
    Inscrit en
    Juillet 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Analyste programmeur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2016
    Messages : 34
    Par défaut System.Reflection SetValue dans un élément List(Of)
    Bonjour,
    Je vous contacte car je sèche ! J'espère que je trouverais mes réponses ici

    J'ai un module comprenant 2 fonctions, il me permet d'exporter un objet vers une chaîne de caractère et ainsi stocker ça dans un fichier et inversement récupérer les données du fichier pour "reconstruire" mon objet avec les valeurs initiale.

    Seulement voilà, dès que j'arrive au moment où je dois réalimenté un élément de type List(Of) ça ne fonctionne pas. J'ai essayé tout un tas de truc mais mon élément de liste reste toujours vide !

    Voici le code complet :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    Module IO_Object
     
        Const Separator As String = "="
        Const iObjSeparator As String = "{" 'In object separator
        Const oObjSeparator As String = "}" 'Out object separator
        Const sElSeparator As String = ">" 'Start element separator
        Const eElSeparator As String = "<" 'End element separator
     
        '----------------------------------------------------------------------------------------------------
        'CONVERTION D'UN OBJET EN STRING
        '----------------------------------------------------------------------------------------------------
        ''' <summary>
        ''' Conversion d'une structure en chaîne de caractère.
        ''' </summary>
        ''' <param name="obj">Structure à convertir.</param>
        ''' <returns></returns>
        ''' <remarks>Utilisez la méthode StringToStruct de la même classe pour convertir votre chaîne en structure.</remarks>
        Function ToString(obj As Object) As String
     
            Dim TmpStr As String = ""
            Dim AddStr As String
            Dim SubObj As Object
     
     
            For Each Field As System.Reflection.FieldInfo In obj.GetType().GetFields
                TmpStr += Field.Name & Separator
     
                Try
                    If GetType(IList).IsAssignableFrom(Field.FieldType) AndAlso Field.FieldType.IsGenericType Then 'Contrôle si l'objet est une liste
                        Dim item As IList = DirectCast(Field.GetValue(obj), IList)
     
                        TmpStr += iObjSeparator & vbCrLf
                        If Not IsNothing(item) Then
                            For Each o As Object In item
                                TmpStr += sElSeparator & vbCrLf
                                TmpStr += ToString(o)
                                TmpStr += eElSeparator & vbCrLf
                            Next
                        End If
                        TmpStr += oObjSeparator & vbCrLf
     
                    Else
                        AddStr = Field.GetValue(obj) & vbCrLf
                        TmpStr += AddStr
                    End If
     
                Catch ex As Exception
                    'Imbrication d'objet
                    SubObj = Field.GetValue(obj)
                    TmpStr += iObjSeparator & vbCrLf
                    TmpStr += ToString(SubObj) & oObjSeparator & vbCrLf
                End Try
     
            Next
     
            Return TmpStr
        End Function
        '----------------------------------------------------------------------------------------------------
        'CONVERTION D'UNE STRING EN OBJET
        '----------------------------------------------------------------------------------------------------
        ''' <summary>
        ''' Conversion d'une chaîne de caractère en objet.
        ''' </summary>
        ''' <param name="Expression">Chaîne de caractère à convertir</param>
        ''' <param name="Obj">Structure à retourner</param>
        ''' <remarks>La chaîne de caractère doit contenir autant de ligne que de champ. La valeur des champs est identifiée par "=".</remarks>
        Function ToObject(ByVal Expression As String, ByRef Obj As Object) As Object
     
            Dim TmpStr As String = ""
            Dim Hash() As String, SubStr() As String, Str As String, GetExpression As String
            Dim fields() As System.Reflection.FieldInfo = Obj.GetType().GetFields(System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.Public)
            Dim NewObj As Integer, NewElement As Integer
            Dim SubObj As Object, NameObj As String
     
            Hash = Strings.Split(Expression, vbCrLf)
            GetExpression = ""
            SubObj = Nothing
            NameObj = ""
     
            For Each Str In Hash
     
                SubStr = Strings.Split(Str, Separator)
     
                If SubStr.Length < 1 Then
                    Continue For
                End If
     
                '---------------------------------------------------
                'Evaluation d'imbrication d'objet
                '---------------------------------------------------
                Select Case SubStr.Last
                    Case iObjSeparator 'Imbrication d'objet
                        If NewElement > 0 Then Exit Select
     
                        NewObj += 1
     
                        If NewObj = 1 Then
                            GetExpression = ""
     
                            For Each Field As System.Reflection.FieldInfo In fields
                                If Field.Name = SubStr(0) Then
                                    SubObj = Field.GetValue(Obj)
                                    NameObj = Field.Name
                                    Exit For
                                End If
                            Next
     
                            Continue For
                        End If
     
                    Case oObjSeparator 'Fin de l'objet imbriquer
                        NewObj -= 1
     
                        If NewObj = 0 Then
                            NewElement = 0
                            If Not IsNothing(SubObj) Then SubObj = ToObject(GetExpression, SubObj)
                        End If
     
                    Case sElSeparator 'Element d'une liste
                        NewElement += 1
     
                        If NewElement = 1 Then
                            GetExpression = ""
                            Continue For
                        End If
                    Case eElSeparator 'Fin de l'élément
                        SubObj.Add(Nothing)
     
                        If Not IsNothing(SubObj) Then SubObj.Item(NewElement - 1) = ToObject(GetExpression, SubObj.Item(NewElement - 1))
                        GetExpression = ""
                        Continue For
     
                    Case Else
                        If NewObj = 0 And NewElement = 0 Then
                            NameObj = SubStr(0)
                            If NameObj = "" Then Continue For
     
                            SubObj = SubStr.Last
                        End If
     
                End Select
     
                '---------------------------------------------------
                'Récupération et affectation des champs de l'objet
                '---------------------------------------------------
                If NewObj > 0 Or NewElement > 0 Then
                    GetExpression += Str & vbCrLf
                Else
     
                    For Each Field As System.Reflection.FieldInfo In fields
                        If Field.Name = NameObj Then
                            If Field.FieldType.BaseType.Name <> "Enum" Then
                                Try
                                    Field.SetValue(Obj, Convert.ChangeType(SubObj, Field.FieldType))
                                Catch ex As Exception
                                    MsgBox("Des données n'ont pas pu être restauré", MsgBoxStyle.OkOnly)
                                End Try
     
                            Else
                                Field.SetValue(Obj, CInt(SubStr(1)))
                            End If
     
                            Exit For
                        End If
     
                    Next
     
                End If
     
            Next
     
            Return Obj
     
        End Function
    End Module
    Voici la partie de code qui me résiste, elle se trouve dans ToObject():

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                    Case eElSeparator 'Fin de l'élément
                        SubObj.Add(Nothing)
     
                        If Not IsNothing(SubObj) Then SubObj.Item(NewElement - 1) = ToObject(GetExpression, SubObj.Item(NewElement - 1))
                        GetExpression = ""
                        Continue For
    J'espère avoir données assez d'explication et merci de votre temps.

  2. #2
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 930
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 930
    Par défaut
    Je ne comprends pas la logique de ce code !

    SubObj.Add(Nothing) ajoute un élément null dans SubObj.

    Ensuite, tu as mis If Not IsNothing(SubObj).
    Ce qui constitue une aberration.
    Puisque tu as déjà utilisé SubObj.Add(Nothing) alors SubObj est assigné !

    Et pour finir SubObj.Item(NewElement - 1) = ToObject(GetExpression, SubObj.Item(NewElement - 1)) :
    Tu affectes à SubObj.Item(NewElement - 1) un élément construit à partir de GetExpression qui contient une chaîne vide (si je ne fait pas erreur mais ton code est compliqué à souhait pour pas grand chose) et de SubObj.Item(NewElement - 1) qui est nul.

    Pourquoi réinventer la roue ?
    Il existe des outils de sérialisation pour faire ce job.

  3. #3
    Membre averti
    Homme Profil pro
    Analyste programmeur
    Inscrit en
    Juillet 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Analyste programmeur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2016
    Messages : 34
    Par défaut
    Bonjour Popo,

    Afin de répondre efficacement :
    1 Le code n'est pas encore nettoyer et en test, donc oui dans cette partie il y'a des instructions inutile.
    2 Pourquoi réinventé la roue, parce que l'application est veille et que c'est un update avec ajout de fonctions et ça a été développé comme ça à l'origine.
    3 La chaîne n'est pas vide, car je sais encore utiliser un débuggeur de plus avant de jeter mon code sur le forum où de poser des questions je fais mes propres recherche.

    Et en quoi cela est un problème de ne pas utiliser les objets conventionnel ? Chacun fais ce qui veut, c'est là tout l'intérêt du codage, mais là n'est pas la question.

  4. #4
    Expert confirmé
    Avatar de popo
    Homme Profil pro
    Analyste programmeur Delphi / C#
    Inscrit en
    Mars 2005
    Messages
    2 930
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Analyste programmeur Delphi / C#
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 2 930
    Par défaut
    Afin de te faire comprendre pourquoi encore une fois je ne trouve pas de logique à ce que tu racontes.

    Ton point 1 precise que le code est en test et non nettoyé. Cela implique qu'il n'est pas là depuis longtemps et par extension cela entre en totale contradiction avec ton point 2 qui précise que c'est le code d'origine.

    Pour ton point 3, tu viens quémander de l'aide sur un sujet largement documenté sur le net. Donc mets ton ego de côté et surtout pars du principe que nous ne connaissons rien de ton parcours professionnel.

    Pourquoi cela pose problème de ne pas utiliser la méthode conventionnelle ? Cela tient en un mot : "maintenabilité". A moins que tu travailles tout seul dans ton coin, utiliser des objets, des méthodes ou des patterns reconnus permets aux autres développeurs de comprendre ton code plus facilement. La sérialisation d'objets est un classique qui se résoud très simplement avec les méthodes conventionnelles. Et réinventer la roue, surtout sur ce sujet est contre-productif. Ce n'est pas cela l'objectif du codage. L'objectif du codage est de réaliser un traitement de manière efficace pour celui qui utilise ton programme.

    Comme tu l'as dit, tu fais comme tu veux.
    Suis les conseils qu'on te donne ou ne les suis pas mais, dans ce cas, assumes et débrouille toi tout seul.

    Moi, je n'utilise pas ton programme alors je me fiche bien de la manière dont tu l'écris.

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Septembre 2010
    Messages
    1 512
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Septembre 2010
    Messages : 1 512
    Par défaut
    L'erreur (a priori, en tout cas celle que j'ai) c'est que SubObj est Nothing à un moment, donc la méthode Add échoue (logique).
    Déjà il y a un souci dans ToString avec une List(Of), j'ai testé avec une List(Of Integer) et je n'ai pas mes valeurs, j'ai 2 champs MinValue et MaxValue (qui correspondent aux limites du type Integer)
    Voilà ce que j'ai testé (testé aussi changeant Structure par Class, même souci)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
        Structure Toto
            Public ValueOne As List(Of Integer)
            Public ValueTwo As Boolean
            Public ValueString As String
        End Structure
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim dummy As Toto
            dummy.ValueOne = New List(Of Integer)
            dummy.ValueOne.Add(12)
            dummy.ValueOne.Add(15)
            dummy.ValueOne.Add(56)
            dummy.ValueTwo = False
            dummy.ValueString = "je suis un toto qui s'appelle dummy"
     
            TextBox2.Text = IO_Object.ToString(dummy)
     
            Dim dummy2 As Toto
            dummy2 = IO_Object.ToObject(TextBox2.Text, dummy2)
     
        End Sub
    Mon Texbox2 contient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "ValueOne={" & vbCrLf & ">" & vbCrLf & "MaxValue=2147483647" & vbCrLf & "MinValue=-2147483648" & vbCrLf & "<" & vbCrLf & ">" & vbCrLf & "MaxValue=2147483647" & vbCrLf & "MinValue=-2147483648" & vbCrLf & "<" & vbCrLf & ">" & vbCrLf & "MaxValue=2147483647" & vbCrLf & "MinValue=-2147483648" & vbCrLf & "<" & vbCrLf & "}" & vbCrLf & "ValueTwo=False" & vbCrLf & "ValueString=je suis un toto qui s'appelle dummy" & vbCrLf

  6. #6
    Membre averti
    Homme Profil pro
    Analyste programmeur
    Inscrit en
    Juillet 2016
    Messages
    34
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Analyste programmeur
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Juillet 2016
    Messages : 34
    Par défaut
    Popo,
    Je pense que tu as mal compris, c'est l'upgrade qui est en cours de debug.
    Donc il n'est pas là question d'égo, mais d'adaption d'un code existant.

    Umfred,
    Merci pour ton approche effectivement, il y'a un loup, de côté là que j'ai pu corriger mais dans la restauration de données ça ne reste pas vraiment pas stable.

    Je voulais éviter de passer par un autre système de fichier, mais je pense que je vais y passer encore beaucoup de temps si je veux adapter ça aux nouvelles fonctionnalités.

    Donc conclusion, la sérialisation paraît être effectivement le plus adapté, à moi de coder une fonction qui fera le tri entre ancien fichiers et nouveaux...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 20
    Dernier message: 27/07/2010, 15h52
  2. [XSD] éléments uniques dans un xsd:list
    Par nono_31 dans le forum Valider
    Réponses: 5
    Dernier message: 20/08/2009, 09h39
  3. Table inline dans un élément de liste
    Par schnee dans le forum Mise en page CSS
    Réponses: 5
    Dernier message: 30/04/2009, 15h26
  4. Réponses: 1
    Dernier message: 04/12/2008, 13h51
  5. Recherche dans les éléments d'une liste
    Par adelotti dans le forum VBA Word
    Réponses: 12
    Dernier message: 19/06/2008, 16h52

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo