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 :

Comment rajouter dynamiquement des propriétés à une classe ?


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Par défaut Comment rajouter dynamiquement des propriétés à une classe ?
    Salut tout le monde,

    voici mon besoin, pouvoir associer de nouvelles propriétés à un objet de façon dynamique. Ces nouvelles propriétés ayant une accessibilité limitée, par exemple limitée à une méthode qui introduit ces nouvelles propriétés.

    Je donne un petit exemple, dans une application, j'ai une classe Champ qui possède un certain nombre de propriétés, mais il ne possède pas la propriété Index du type int car cet index ne signifie rien pour un champ.

    Par contre, j'ai besoin dans une méthode qui utilise une utilise de champs d'associer un index pour chacun de ces champs.

    Pour ce faire, j'ai actuellement 2 possibilités, mettre l'index dans un Tag, sauf que le Tag est du type object, il faut donc faire un cast à chaque fois que je l'utilise et il se peut qu'il possède une autre information qui sera perdue.
    Autre soucis, le terme Tag n'est pas parlant pour reconnaitre le rôle de la propriété.

    Autre possibilité, je peux faire une liste d'int dont chaque valeur est l'int associé au champ qui se trouve à la même position dans la liste des champs.
    Problème : il faut être sûr que les listes sont toujours bien synchronisées, de plus je ne peux plus faire de :
    foreach(Champ champ in liste) car je dois avoir sa position dans la liste, il faut donc faire : for(int i=0;i<liste.Count;i++)
    Ca signifie que ça m'impose de travailler avec une liste et non plus une simple énumération de champs, ce qui peut être contraignant.

    Ceci n'est qu'un exemple simplifiant le besoin car en réalité, j'ai besoin d'associer plus qu'un int à mon champ, je dois aussi pouvoir lui associer une List.

    Au final, ce besoin ressemblerait en quelques sorte aux extensions de méthodes sauf que ce serait des extensions de propriétés et que ça n'existe pas.

    M'avez-vous suivi dans mon besoin ? Quelle est la solution pour répondre au besoin d'après vous ?

    Merci par avance pour vos conseils.

  2. #2
    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
    Dans ce genre de cas, j'utiliserais un dico.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    private Dictionary<Champ, int> dico = new ...;
     
    public int GetIndex(Champ c)
    {
      int result = 0;
      dico.TryGetValue(c, out result);
      return result;
    }
     
    public void SetIndex(Champ c, int i)
    {
      dico[c] = i;
    }
    Parce qu'à moins que tu veuilles faire du binding, le fait que "à tel objet est rattaché telle valeur" n'a pas besoin de s'exprimer sous forme d'une propriété.

    J'ajoute que bien sûr ces méthodes Get et Set peuvent être transformées en méthodes d'extension éventuellement. Il faudra alors écrire monChamp.GetIndex(). Ouala, ce genre de code ressemble à du java mais ça marche

  3. #3
    Membre éclairé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Par défaut
    Salut,

    ton code signifie que la portée du dico est celle de la classe et non celle de la méthode.
    De plus, pour récupérer l'index du champ, il faut retrouver ce dit champ dans le dico.
    Et il faut déclarer un nouveau dico pour chaque nouvelle propriété avec chaque nous type.

    En fait, entre temps, j'ai trouvé une solution, qui n'est certainement pas très évidente à utiliser mais semble fonctionner :
    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
        public class ExtensionDePropriete
        {
            private Dictionary<string, object> _Dico = new Dictionary<string, object>();
     
            public void Vider()
            {
                _Dico.Clear();
            }
     
            public T GetPropriete<T>(string propriete)
            {
                return (T)_Dico[propriete];
            }
            public void SetPropriete<T>(string propriete, T valeur)
            {
                _Dico[propriete] = valeur;
            }
        }
    Ensuite, je rajoute une propriété ExtensionDePropriete au champ :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public Champ
        {
            // ...
            #region ExtensionDePropriete
            private ExtensionDePropriete _ExtensionDePropriete = new ExtensionDePropriete();
            public ExtensionDePropriete ExtensionDePropriete { get { return _ExtensionDePropriete; } }
            #endregion
            // ...
    Et pour l'utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    // ...
    champ.ExtensionDePropriete.SetPropriete<int>("Index", 0);
    // ...
    MessageBox.Show(champ.ExtensionDePropriete.GetPropriete<int>("Index").ToString());
    C'est clair que c'est pas super pratique à l'utilisation en fait, j'espère trouver une solution pour simple.

  4. #4
    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 WebPac Voir le message
    ton code signifie que la portée du dico est celle de la classe et non celle de la méthode.
    Si ça t'ennuie, tu peux mettre le dico dans une classe que tu instancieras dans ta méthode
    Citation Envoyé par WebPac Voir le message
    De plus, pour récupérer l'index du champ, il faut retrouver ce dit champ dans le dico.
    Si le champ a jamais été affecté, alors Index vaudra 0, ce qui est la valeur par défaut pour un int. Même comportement que si Index était une propriété.
    Citation Envoyé par WebPac Voir le message
    Et il faut déclarer un nouveau dico pour chaque nouvelle propriété avec chaque nous type.
    Si tu veux enrichir une classe Champ avec n propriétés, tu peux écrire une classe (ou struct) ChampComplément par exemple, et avoir un dico qui associe à un Champ un ChampComplément.

    Où tu peux simplement encapsuler ton Champ dans une autre classe, ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class ExtendedChamp
    {
      public Champ Champ;
      public int Index;
      public string Bidule, Chouette;
    }
    public void f(Champ c)
    {
      ExtendedChamp ec = new ExtendedChamp(c);
      ec.Index = ....;
    }
    la solution que tu proposes est valable aussi, mais je passerais par des enum plutôt que par des strings, parce que le compilo ne peut faire aucune vérification statique sur les chaînes.

  5. #5
    Membre éclairé Avatar de WebPac
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2004
    Messages : 947
    Par défaut
    Citation Envoyé par Guulh Voir le message
    Si ça t'ennuie, tu peux mettre le dico dans une classe que tu instancieras dans ta méthode
    En effet, l'endroit où est déclaré le dico n'est pas vraiment important.

    Citation Envoyé par Guulh Voir le message
    Si le champ a jamais été affecté, alors Index vaudra 0, ce qui est la valeur par défaut pour un int. Même comportement que si Index était une propriété.
    Mon soucis était plus de l'ordre de l'optimisation car si j'ai une centaine de champs, je dois retrouver 100x un champ dans un dico de 100 entrées.

    Citation Envoyé par Guulh Voir le message
    Si tu veux enrichir une classe Champ avec n propriétés, tu peux écrire une classe (ou struct) ChampComplément par exemple, et avoir un dico qui associe à un Champ un ChampComplément.

    Où tu peux simplement encapsuler ton Champ dans une autre classe, ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    class ExtendedChamp
    {
      public Champ Champ;
      public int Index;
      public string Bidule, Chouette;
    }
    public void f(Champ c)
    {
      ExtendedChamp ec = new ExtendedChamp(c);
      ec.Index = ....;
    }
    la solution que tu proposes est valable aussi, mais je passerais par des enum plutôt que par des strings, parce que le compilo ne peut faire aucune vérification statique sur les chaînes.
    J'avais aussi pensé à cette solution, je l'avais d'ailleurs implémentée de façon générique afin de pouvoir la réutiliser avec d'autres classes que le champ mais cela signifiait que si j'avais une énumération de champs, je devais créer une énumération d'ExtendedChamp, je passais ma liste de champs pour créer les ExtendChamp. Et par la suite, je ne devais plus travailler avec l'énumération de champs mais avec l'énumération d'ExtendChamp.

    Vous pouvez trouver que je pinaille, mais ça peut-être perturbant pour un programmeur tiers qui doit reprendre le code et se dit "mais pourquoi il me fait un foreach sur une autre liste que ma liste de champs ?".

    Je pense continuer avec ExtensionDePropriete pour l'instant comme ça fonctionne et garder ça derrière une oreille car je ne pense pas qu'avec le Framework actuel on puisse le faire autrement.

    Merci en tout cas pour ton intervention et si tu as d'autres idées, je suis preneur.

Discussions similaires

  1. [XL-2003] Ajouter dynamiquement des Events à une Feuille via un module de classe.
    Par comme de bien entendu dans le forum Excel
    Réponses: 4
    Dernier message: 10/06/2012, 07h11
  2. [XL-2003] Ajouter dynamiquement des Events à une Feuille via un module de classe.
    Par comme de bien entendu dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 08/06/2012, 18h06
  3. Kompozer Attribuer des propriétés à une classe
    Par Jean Sympa dans le forum Mise en page CSS
    Réponses: 2
    Dernier message: 15/11/2010, 10h46
  4. comment ajouter des méthodes à une classe lors Runtime?
    Par revever dans le forum Collection et Stream
    Réponses: 2
    Dernier message: 31/03/2008, 13h53
  5. Réponses: 5
    Dernier message: 15/02/2008, 21h10

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