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 :

Problème avec les types


Sujet :

VB.NET

  1. #1
    Membre averti
    Inscrit en
    Juin 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 14
    Par défaut Problème avec les types
    Bonjour,

    j'ai une application (ASP.NET 2, VB) dans laquelle sont définies des classes (ClassAlpha, ClassBeta, ...) dans des fichiers .vb de la manière suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Public Class ClassAplha
        'mon code (propriétés et méthodes)
    End Class
    A un moment dans mon application, je récupère une chaîne de caractères (appelons la strMaClasse) qui contient le nom d'une de mes classes (donc "ClassAlpha" ou "ClassBeta", etc.)

    J'ai besoin à ce moment de déclarer un objet (appelons le monObjet) du type de la classe correspondant à la chaîne de caractères strMaClasse.

    Donc littéralement cela aurait put s'écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim monObjet As strMaClasse
    Evidemment cela ne fonctionne pas car strMaClasse n'est pas un type mais une chaîne de caractères.
    J'ai essayé plein de choses pour convertir cette chaîne dans le type correspondant mais sans succès.

    Comment puis-je faire ?

  2. #2
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2005
    Messages : 80
    Par défaut
    Il te faut passer par les fonctions de Reflection de .NET. Il te faut charger l'assembly qui contient les types que tu veux appeler. Pour ce faire, tu dois le charger en code et aller chercher le type voulu et l'instancier.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Dim Assembly As Reflection.Assembly = Reflection.Assembly.Load("MonAssembly")
    Dim monObjet As New Object
    'Il faut charger le type avec son nom long absolument, pour le connaitre
    'tu peux le chercher dans ton objet Assembly.GetTypes avec la propriété FullName
    MonObjet = Assembly.CreateInstance("MonType")
    'Puis après, tu peux lancer tes Sub, Function ou autre de ton type avec la variable MonObjet

  3. #3
    Membre averti
    Inscrit en
    Juin 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 14
    Par défaut
    Merci Zyth pour cette réponse rapide.
    La réflection hein... j'avais bien lu quelques trucs là-dessus mais ça m'avait semblé l'enfer à utiliser faute d'exemple clair et j'avais espéré pouvoir m'en passer.
    En revanche ton exemple me semble assez simple et je vais tenter le coup comme ça.

    J'ai néanmoins quelques questions complémentaires.

    Tu dis que je dois charger l'assembly contenant mes classes... c'est quoi une assembly ? toutes mes classes sont dans des fichiers .VB dans le répertoire App_Code de mon application, elles ne sont pas déjà chargées ? Pourtant je peux les utiliser sans problème en faisant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim maClasse As ClassAlpha
    n'importe où dans mon code... Cela veut-il dire que je dois en faire une DLL séparée ? Si oui je ne suis pas sûr de savoir comment faire ça.

    J'avais aussi vu l'existence de System.ComponentModel.TypeConverter avec des méthodes genre .ConvertFrom dont la fonction est (je cite l'aide en ligne) Convertit un String en Type mais là encore impossible de trouver le moyen de l'utiliser faute d'exemple...

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2005
    Messages : 80
    Par défaut
    Un assembly regroupe une multitude de types et est retrouvé en un fichier exécutable ou une dll. Tu n'es pas obligé de mettre ta classe dans une dll séparée et tu devras "recharger" l'assembly (ou le projet) que tu es en train de faire.
    Je vais te donner un exemple avec mon projet qui s'appelle "Testt" et qui contient ma classe "Form1" qui contient une procédure nommée "Testing".
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
            Dim Assembly As Reflection.Assembly = Reflection.Assembly.Load("Testt") 
            Dim Test As New Object
            Test = Assembly.CreateInstance("WindowsApplication1.Form1")
            Test.Testing()
    Donc, bien que je recharge mon présent projet (note que ça fonctionne aussi bien pour un dll externe), j'appelle dynamiquement ma procédure !

  5. #5
    Membre averti
    Inscrit en
    Juin 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 14
    Par défaut
    OK, donc je ne suis pas obligé de compiler séparément mes classes dans une DLL (bien parce que je ne saurais pas vraiment comment faire, ni après comment lier cette DLL avec mon application).

    Par contre chez moi il s'agit d'une application Web et non Windows. Et en essayant d'appliquer ton exemple à mon cas j'ai une FileNotFound exception sur la première ligne.

    Je ne dois visiblement pas mettre les bonnes informations dans les string, voici ce que j'ai fait:

    Ma solution s'appelle maSolution
    Dans cette solution j'ai un projet (de type ASP.NET Web Application) nommé par son chemin physique sur mon disque dur (D:\Documents and Settings\Alain\Mes documents\Projets\MonProjet)
    Dans ce projet j'ai un sous répertoire (créé automatiquement par VS) nommé App_Code dans lequel se trouvent les fichiers .VB contenant mes classes (par exemple ClassAlpha.vb)
    Dans ce fichier ClassAlpha.vb j'ai une classe publique nommée ClassAlpha (aucune mention de namespace nulle part)

    Donc sur ton exemple j'ai fait le code suivant qui plante en première ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Dim Assembly As Reflection.Assembly = Reflection.Assembly.Load("maSolution")
            Dim maClasse As New Object
            maClasse = Assembly.CreateInstance("monProjet.ClassAlpha")
            Dim id As Integer = maClasse.ID
    (.ID est une propriété présente dans ClassAlpha)

  6. #6
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2005
    Messages : 80
    Par défaut
    J'ai fais quelque fois du ASP.NET mais pas assez pour me rappeler exactement comment que ça fonctionne. Je te conseillerais de rechercher un fichier dll dans les dossiers de ta solution et de le prendre avec son chemin pour charger l'assembly. Il se peut si ma mémoire est bonne que le fichier ait un nom bizarre avec plein de caractères ... Désolé d'être flou mais c'est loin dans ma tête (en plus de ne pas avoir présentement accès à un projet ASP.NET ...).

  7. #7
    Membre averti
    Inscrit en
    Juin 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 14
    Par défaut
    Merci Zyth, je progresse pas mal grâce à toi.

    J'ai donc réussi à instancier ma classe ClassAlpha avec le code suivant sans nécessiter de DLL séparée (en fait il semble que VS soit assez intelligent pour associer automatiquement ce fichier .vb à une DLL à lui qu'il créé lors de la compilation du projet):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Dim AssemblyClassAlpha As Reflection.Assembly = Reflection.Assembly.Load("App_Code\ClassAlpha.vb")
    Dim ObjectAlpha As New Object
    ObjectAlpha = AssemblyClassAlpha.CreateInstance("ClassAlpha")
    ObjectAlpha me permet alors d'invoquer les propriétés et méthodes de ma ClassAlpha.
    Jusque là tout baigne


    Malheureusement c'est après qu'il y a un os car j'ai une deuxième classe (ClassBeta) qui possède une méthode (maMéthode) retournant une liste d'instances de ClassAlpha et définie de la manière suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Public Function maMéthode(ByVal Argument1 As String) As List(Of ClassAlpha)
    Or si je suis la logique de la réflection (en tout cas telle que je la comprends) je devrais écrire le code suivant pour utiliser dynamiquement maMéthode:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Dim AssemblyClassAlpha As Reflection.Assembly = Reflection.Assembly.Load("App_Code\ClassAlpha.vb")
    Dim ObjectAlpha As New Object
    ObjectAlpha = AssemblyClassAlpha.CreateInstance("ClassAlpha")
    Dim AssemblyClassBeta As Reflection.Assembly = Reflection.Assembly.Load("App_Code\ClassBeta.vb")
    Dim ObjectBeta As New Object
    ObjectBeta = AssemblyClassBeta.CreateInstance("ClassBeta")
    Dim maListe As List(Of ObjectAlpha) = ObjectBeta.maMéthode(Argument1)
    Malheureusement Dim maListe As List(Of ObjectAlpha) ne fonctionne pas car ObjectAlpha n'est pas un type
    Arghhh, je suis donc à nouveau bloqué car j'ai essayé plein de choses mais je ne vois pas quoi mettre dans ce (Of ...)

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2005
    Messages : 80
    Par défaut
    Tu devras te faire une variable de type List(Of Object) dans le code présent à la place et tu auras accès quand même aux membres de ta classe Alpha. Le type object est celui de base à tous les objets qui existent en .NET, donc il peut passer comme un "joker" si on peut dire .

  9. #9
    Membre averti
    Inscrit en
    Juin 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 14
    Par défaut
    Hmmm, ok, si je comprends bien dans mon code ci-dessous je dois remplacer la dernière ligne par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim maListe As List(Of Object) = ObjectBeta.maMéthode(Argument1)
    donc (Of Object) au lien de (Of ObjectAlpha).

    Cela passe effectivement à la compilation mais lors de l'exécution la ligne me renvoie l'erreur suivante:
    Impossible d'effectuer un cast d'un objet de type 'System.Collections.Generic.List`1[ObjectAlpha]' en type 'System.Collections.Generic.List`1[System.Object]

    Désolé, j'ai vraiment l'impression d'être un vrai boulet avec ce truc, en tout cas j'apprécie vraiment ton aide

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2005
    Messages : 80
    Par défaut
    Disons que les List ne se convertissent pas automatiquement et j'ai oublié ce léger détail. Il faudrait que dans ta ClassBeta ta fonction retourne elle aussi une List(Of Object). Et non tu n'es pas boulet, je ne suis pas vraiment plus familier que toi sur ce concept .

  11. #11
    Membre averti
    Inscrit en
    Juin 2006
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Juin 2006
    Messages : 14
    Par défaut


    Pour Zyth HIP HIP HIP HOURRA !!!

    Ça semble fonctionner.
    Ça me fait des p.. de changements dans mon code (parce que les ClassAlpha et ClassBeta il y en a plusieurs dizaines et pas mal de méthodes avec des list (of ...) dans chaque) mais sous réserve que ça ne plante pas le reste de mon appli (va me falloir pas mal de tests de régression) et que ça ne tue pas les performances (j'avais toujours lu qu'il fallait autant que possible éviter de déclarer As Object) c'est une solution qui semble fonctionner dans mon cas donc: Merci Zyth

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    80
    Détails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Mars 2005
    Messages : 80
    Par défaut
    Je ne crois pas que c'est un grand ralentissement le fait d'utiliser des Object, mais dans ce cas-ci, je crois que nous n'avons pas le choix. Le fait qu'on ne sait pas à l'avance la classe à instancier, on doit jouer avec le plus de liberté possible . Content d'avoir pu te débloquer .

  13. #13
    Membre confirmé
    Inscrit en
    Décembre 2003
    Messages
    111
    Détails du profil
    Informations forums :
    Inscription : Décembre 2003
    Messages : 111
    Par défaut
    Bonjour,

    Si la class à laquelle on veut accéder se trouve dans un module le code est le suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Dim Serv As New Object
     
    Dim Assembly As Reflection.Assembly = Reflection.Assembly.Load("Nom_Du_Projet")
    Serv = Assembly.CreateInstance("Nom_Du_Projet.Nom_Du_Module+Nom_De_La_Class")
    Ca évitera peut être des recherches si quelqu'un cherche la même chôse que moi

    J'en profite aussi pour rapeller que, comme l'a dit Zith, Assembly.GetTypes est une mine d'information...

    Bonne journée et merci pour votre aide

  14. #14
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 204
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 204
    Par défaut
    si les classes sont toutes les 2 un type d'une chose globale, il y a aussi les interfaces qui sont pratiques
    car on peut déclarer des objet en tant qu'interface ...
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 17/01/2008, 13h18
  2. [Migration BDE en ADO][SQLServer] Problème avec les types char
    Par pitango dans le forum Bases de données
    Réponses: 3
    Dernier message: 15/03/2007, 17h17
  3. Problème avec les types de variable
    Par binhjuventus dans le forum C++Builder
    Réponses: 2
    Dernier message: 13/07/2006, 12h30
  4. Réponses: 1
    Dernier message: 25/11/2005, 20h40
  5. [Débutant][Phppgadmin] problème avec les types
    Par PoY dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 19/08/2004, 17h06

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