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

C# Discussion :

Appel dynamique d'un attribut d'un object


Sujet :

C#

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut Appel dynamique d'un attribut d'un object
    Bonjour,

    Voilà j'ai un Objet de nom MonObjet, instance de la classe MaClasse, avec 2 attributs que j'appelle attribut1, attribut2.

    Quand on veut changer un attribut, par exemple l'attribut1, on fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MonObjet.attribut1 = maNouvelleValeur;
    Ce que j'aimerai faire, c'est passer un paramètre nomAttribut de type String et allouer la valeur à l'attribut de cet objet qui porte ce nom, alors je peux faire un enchaînement de if, par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    if (nomAttribut.equals("attribut1")
    {
    monObjet.attribut1 = maNouvelleValeur;
    }
    else if (nomAttribut.equals("attribut2")
    {
    monObjet.attribut2 = maNouvelleValeur;
    }
    Ici, je n'ai que 2 attributs, mais dans mon travail, j'ai pleins d'attributs, et ce n'est pas la seule raison de ma recherche, je ne détaille pas toute la complexité de mon projet!

    Donc, nous y voilà:
    Y'aurait il un moyen de faire quelque chose du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    monObjet.typeAttribut = maNouvelleValeur;
    Où typeAttribut est l'attribut de nom nomAttribut (donc soit attribut1, soit attribut2).
    J'espère que je me suis bien expliqué?

    Merci de m'aider!

  2. #2
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    Bonjour,

    Oui tu peux faire cela avec un peu de reflexion, voici un bout de code qui t'aidera :

    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
     
    public class Class1
    {
     
        public string Variable
        {
            get;
            set;
        }
    }
     
    class Program
    {
        static void Main(string[] args)
        {
            Class1 classe = new Class1();
            Type type = typeof(Class1);
            PropertyInfo prop = type.GetProperty("Variable");
            prop.SetValue(classe, "caca", null);
            Console.WriteLine(classe.Variable);
            Console.Read();
        }
    }
    Pour plus d'infos, voici un tuto DVP sur la reflexion : http://emerica.developpez.com/dotnet...uction/csharp/

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    Ok merci, tu m'as lancé sur la piste!

    Sais tu s'il est possible de récupérer la valeur de cet attribut de nom nomAttribut, dans une variable de type TypeAttribut?

    En gros:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    TypeAttribut maVariable = monObjet.typeAttribut;
    Où typeAttribut est l'attribut de nom nomAttribut.

    J'ai fouillé dans les attributs et méthodes de PropertyInfo mais je ne vois rien qui pourrait répondre à ma question...

    Merci de ton aide!

  4. #4
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    Mhh, je suis un peu perdu par ton explication, mais si tu veux récupérer la valeur d'un attribut tu dois faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Class1 classe = new Class1();
    Type type = typeof(Class1);
    PropertyInfo prop = type.GetProperty("NomPropriété");
    object valeur = prop.GetValue(classe,null));
    NomPropriété est le nom de la propriété dont tu veux récupérer la valeur. Et tu dois passer la référence de l'objet souhaité à la méthode GetValue de PropertyInfo pour récupérer la valeur de la propriété.

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    Ce que tu me dis va dans le bon sens par rapport à ce que je cherche.

    Je reéxplique:

    La valeur que tu as récupérée est de type Object.
    Ce que j'aimerai est que la valeur soit récupéré dans une variable de type identique à celui de l'attribut récupéré.

    Par exemple, si l'attribut récupéré est un string, automatiquement, la valeur récupérée est de type string, etc.

  6. #6
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    Ok, c'est possible aussi, mais il y a des limitations. Tu peux récupérer le type de la propriété, instancier une variable de ce type avec la classe statique Activator, cependant, s'il n'y a pas de constructeur par défaut, tu auras une jolie exception. Rien de grave, mais va falloir rajouter un peu de logique dans le cas où ton type n'a pas de constructeur par défaut, voici un exemple :

    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
     
    Class1 classe = new Class1
    {
        Variable = "caca"
    };
    Type type = typeof(Class1);
    PropertyInfo prop = type.GetProperty("Variable");
     
    Type typePropriété = prop.PropertyType;
    var contientConstructeurSansParam = typePropriété.GetConstructors().Any(cInfo => cInfo.GetParameters().Count() == 0);
     
    object var;
    if (contientConstructeurSansParam)
        var = Activator.CreateInstance(prop.PropertyType);
    else if (typePropriété == typeof(string))
        var = string.Empty;
     
    var = prop.GetValue(classe, null);
    La définition de Class1 est dans mon 1er post. L'objet var est bien type string si la propriété est de type string, et autre si c'est le type de la propriété a un constructeur par défaut.

    Tu peux tester, en faisant un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Console.WriteLine(var.GetType().ToString());

  7. #7
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    Euh perso je comprends pas trop à cet endroit là:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var contientConstructeurSansParam = typePropriété.GetConstructors().Any(cInfo => cInfo.GetParameters().Count() == 0);
     
    object var;
    Mais en attendant "bon we"!

  8. #8
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    Cette ligne permet savoir si le type de la propriété contient un constructeur sans paramètre. Any est une méthode d'extension fournit par LinQ qui prend en paramètre un délégué de type Action<T,T1>. Cela m'a évité d'écrire une boucle foreach plus difficilement compréhensible.

    En gros c'est du C# 3. Si tu l'as pas, il faut refaire cette logique avec une boucle foreach. Dis moi si c'est le cas ...

  9. #9
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    Citation Envoyé par Paul Musso Voir le message
    En gros c'est du C# 3. Si tu l'as pas, il faut refaire cette logique avec une boucle foreach. Dis moi si c'est le cas ...
    Effectivement, je n'ai pas C# 3.0... Je veux bien que tu me montres la boucle foreach équivalente!
    Merci!

  10. #10
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    Re et voici la boucle foreach

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    bool contientConstructeurSansParam = false;
    foreach (ConstructorInfo c in typePropriété.GetConstructors())
    {
        if (c.GetParameters().Count() == 0)
        {
            contientConstructeurSansParam = true;
            break;
        }
    }

  11. #11
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    Yeah! Merci de ta réponse!

    Par contre, la méthode Count n'existe pas sur ConstructorInfo.GetParameters()...

  12. #12
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    La propriété Length devrait faire l'affaire alors

    Ah la la, je suis perdu sans le c# 3 ^^

  13. #13
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    ça marche! merci beaucoup!

    Je n'ai quand même pas très bien compris cette partie là:

    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
     
            bool contientConstructeurSansParam = false;
            foreach (ConstructorInfo c in typePropriété.GetConstructors())
            {
                if (c.GetParameters().Length == 0)
                {
                    contientConstructeurSansParam = true;
                    break;
                }
            }
     
            object var;
            if (contientConstructeurSansParam)
                var = Activator.CreateInstance(typePropriété);
            else if (typePropriété == typeof(string))
                var = string.Empty;
    Bref si tu pouvais m'expliquer...

    Merci en tout cas de m'avoir aidé!

  14. #14
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    En fait, je me sers de la classe Activator pour instancier une nouvelle variable du même type que la propriété.

    Cependant, Activator.CreateInstance(typePropriété); appelle en fait le constructeur sans paramètre du type. Si celui-ci ne contient aucun constructeur sans paramètre, alors cette ligne génère une erreur en prétextant qu'il n'a pas trouvé de constructeur sans paramètre.

    Du coup, le foreach permet de savoir si le type en question contient un constructeur sans paramètre. Si c'est le cas, alors Activator.CreateInstance(typePropriété); ne générera pas d'erreur, sinon, il faut fournir les paramètres nécessaires pour instancier le type.

    Dans mon exemple, le sinon n'a pas été implémenté, à la place je teste juste si le type est de type string (if (typePropriété == typeof(string)), mais il est possible de remplacer cette logique par quelque chose de plus générique, qui appelerai par exemple Activator.CreateInstance en lui passant les paramètres nécessaires (il y a plusieurs surcharges de cette fonction).

    Voila, j'espère que c'est un peu plus clair pour toi

  15. #15
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Euh... vous vous compliquez la vie pour pas grand chose, quand même

    En gros, si j'ai bien compris, ce que tu veux, c'est une méthode qui avec une paire (string, object) (le nom de la propriété et un objet), affecte à la propriété la valeur donnée ? A ce moment-là, le code donné par Paul Musso au début du thread est très bien.
    (d'ailleurs, en C#, en n'utilise pas le mot "attribut" dans ce cas. Un attribut, en DotNet, c'est autre chose.)

    Parce que ça sert à quoi, la réflexion, si la méthode qui l'utilise fait des tripotées de "else if" successifs ?
    Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void AffecteValeur(object objet, string nomPropriété, object valeur)
    {
            Type type = typeof(objet);
            PropertyInfo prop = type.GetProperty(nomPropriété);
            prop.SetValue(objet, valeur, null);
    }
     
    AffecteValeur(bidule, "PropriétéDeTypeEntier", 5);
    AffecteValeur(bidule, "PropriétéDeTypeChaine", "Bob");
    La réflexion est très puissante. Mais trop. Et les scénarios dans lesquelles elle s'avère vraiment utile ne sont pas si nombreux.

  16. #16
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    C'est plus clair pour moi!

    Citation Envoyé par Paul Musso Voir le message
    Dans mon exemple, le sinon n'a pas été implémenté, à la place je teste juste si le type est de type string (if (typePropriété == typeof(string)), mais il est possible de remplacer cette logique par quelque chose de plus générique, qui appelerai par exemple Activator.CreateInstance en lui passant les paramètres nécessaires (il y a plusieurs surcharges de cette fonction).
    Par contre, faut-il que je teste égalemment que mon type est un int, un boolean, un datetime, sur le même modèle que toi avec le string?

  17. #17
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    Citation Envoyé par Guulh Voir le message
    Euh... vous vous compliquez la vie pour pas grand chose, quand même

    En gros, si j'ai bien compris, ce que tu veux, c'est une méthode qui avec une paire (string, object) (le nom de la propriété et un objet), affecte à la propriété la valeur donnée ? A ce moment-là, le code donné par Paul Musso au début du thread est très bien.
    (d'ailleurs, en C#, en n'utilise pas le mot "attribut" dans ce cas. Un attribut, en DotNet, c'est autre chose.)

    Parce que ça sert à quoi, la réflexion, si la méthode qui l'utilise fait des tripotées de "else if" successifs ?
    Donc :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void AffecteValeur(object objet, string nomPropriété, object valeur)
    {
            Type type = typeof(objet);
            PropertyInfo prop = type.GetProperty(nomPropriété);
            prop.SetValue(objet, valeur, null);
    }
     
    AffecteValeur(bidule, "PropriétéDeTypeEntier", 5);
    AffecteValeur(bidule, "PropriétéDeTypeChaine", "Bob");
    La réflexion est très puissante. Mais trop. Et les scénarios dans lesquelles elle s'avère vraiment utile ne sont pas si nombreux.
    Oui au début c'était ça, mais maintenant, c'est la récupération d'une valeur d'une propriété d'un objet dans une variable de même type que cette propriété de l'objet, qui m'intéresse...

  18. #18
    Rédacteur
    Avatar de Paul Musso
    Profil pro
    Inscrit en
    Août 2008
    Messages
    368
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Août 2008
    Messages : 368
    Par défaut
    bool, DateTime et int ont tous un constructeur sans paramètre, donc ça passe. Je viens de tester à l'instant ^^

  19. #19
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Citation Envoyé par cyrano_de_bergerac Voir le message
    Oui au début c'était ça, mais maintenant, c'est la récupération d'une valeur d'une propriété d'un objet dans une variable de même type que cette propriété de l'objet, qui m'intéresse...
    D'accord Mais à part la valeur éducative de l'exercice, ça sert à quoi ?

  20. #20
    Membre éclairé
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    343
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 343
    Par défaut
    Citation Envoyé par Paul Musso Voir le message
    bool, DateTime et int ont tous un constructeur sans paramètre, donc ça passe. Je viens de tester à l'instant ^^
    Ok merci beaucoup, je vais pouvoir mettre le topic en résolu!

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. [POO] Appeller dynamiquement un attribut
    Par Raideman dans le forum Langage
    Réponses: 3
    Dernier message: 07/04/2010, 11h32
  2. Appeler dynamiquement une procédure stockée
    Par Mark531 dans le forum Access
    Réponses: 1
    Dernier message: 05/09/2006, 17h49
  3. Appel dynamique de fonctions
    Par smyley dans le forum MFC
    Réponses: 4
    Dernier message: 27/10/2005, 12h53
  4. Réponses: 7
    Dernier message: 03/10/2005, 23h27
  5. Réponses: 4
    Dernier message: 07/12/2002, 07h34

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