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

Contribuez .NET Discussion :

.NET 4 : enrichir List<T> d'un évènement


Sujet :

Contribuez .NET

  1. #1
    Membre actif
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Points : 210
    Points
    210
    Par défaut .NET 4 : enrichir List<T> d'un évènement
    Bonjour,

    Juste pour faire part d'une chose qui peut être utile à certains et qui pourrait pourquoi pas entrer dans les contributions

    J'ai eu besoin d'utiliser une liste qui lance un évènement avant suppression d'un ou plusieurs éléments de cette liste (à la manière des triggers en base de données).

    J'ai donc créé ces deux classes :
    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
      public class BeforeRemoveEventArgs : EventArgs
      {
        public BeforeRemoveEventArgs(object item)
        {
          this.item = item;
        }
     
        public object item;
      }
     
      public class ListTrigerred<T> : List<T>
      {
        public delegate void BeforeRemoveEventHandler(object sender, BeforeRemoveEventArgs e);
        public event BeforeRemoveEventHandler BeforeRemove;
     
        public new bool Remove(T item)
        {
          if (BeforeRemove != null)
          {
            List<T> l = new List<T>();
            l.Add(item);
            BeforeRemove(this, new BeforeRemoveEventArgs(l));
          }
     
          return base.Remove(item);
        }
     
        public new int RemoveAll(Predicate<T> match)
        {
          if (BeforeRemove != null)
            BeforeRemove(this, new BeforeRemoveEventArgs(this.FindAll(match)));
     
          return base.RemoveAll(match);
        }
      }
    L'utilisation se fait comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        public ListTrigerred<Point> lsPoints = new ListTrigerred<Point>();
        lsPoints.BeforeRemove += delegate(object sender, BeforeRemoveEventArgs e)
          {
            List<Point> PointsToRemove = (List<Point>)e.item;
     
            // TODO : implémenter les actions à effectuer avant la suppression des points
          };
    J'ai utilisé une méthode anonyme pour condenser le code mais vous pouvez bien évidemment utiliser une fonction ou autres!
    Le type Point peut être remplacé par n'importe quel type.


    Bon dév,
    Arnaud D.
    --
    Arnaud DANEELS

  2. #2
    Membre actif
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Points : 210
    Points
    210
    Par défaut
    avec l'implémentation de RemoveRange et RemoveAt, c'est mieux :
    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
     
      public class BeforeRemoveEventArgs : EventArgs
      {
        public BeforeRemoveEventArgs(object item)
        {
          this.item = item;
        }
     
        public object item;
      }
     
      public class ListTrigerred<T> : List<T>
      {
        public delegate void BeforeRemoveEventHandler(object sender, BeforeRemoveEventArgs e);
        public event BeforeRemoveEventHandler BeforeRemove;
     
        public new bool Remove(T item)
        {
          if (BeforeRemove != null)
          {
            List<T> l = new List<T>();
            l.Add(item);
            BeforeRemove(this, new BeforeRemoveEventArgs(l));
          }
     
          return base.Remove(item);
        }
     
        public new int RemoveAll(Predicate<T> match)
        {
          if (BeforeRemove != null)
            BeforeRemove(this, new BeforeRemoveEventArgs(this.FindAll(match)));
     
          return base.RemoveAll(match);
        }
     
        public new void RemoveAt(int index)
        {
          if (BeforeRemove != null)
          {
            List<T> l = new List<T>();
            l.Add(this[index]);
            BeforeRemove(this, new BeforeRemoveEventArgs(l));
          }
     
          base.RemoveAt(index);
        }
     
        public new void RemoveRange(int index, int count)
        {
          if (BeforeRemove != null)
            BeforeRemove(this, new BeforeRemoveEventArgs(this.GetRange(index, count)));
     
          base.RemoveRange(index, count);
        }
      }
    --
    Arnaud DANEELS

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Tu peux aussi utiliser BindingList<T> ou ObservableCollection<T>Cela dit ça ne donnera pas exactement le même comportement :

    - l'évènement sera déclenché après l'ajout ou la suppression, et non avant (je ne sais pas si c'est un problème pour l'usage que tu en fais)

    - l'évènement sera déclenché pour chaque élément ajouté ou supprimé, et non pas pour l'ensemble des éléments à ajouter ou supprimer (dans le cas de AddRange/RemoveRange/RemoveAll)

  4. #4
    Membre actif
    Avatar de adaneels
    Homme Profil pro
    Chef de projet MOA
    Inscrit en
    Août 2006
    Messages
    236
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Chef de projet MOA

    Informations forums :
    Inscription : Août 2006
    Messages : 236
    Points : 210
    Points
    210
    Par défaut
    Tout d'abord merci de l'attention portée

    Oui, c'est vrai, j'aurai pu partir sur une ObservableCollection.

    L'implémentation que j'ai faite a pour différences de :
    faire un évènement pour une action (la suppression ici ; je n'aime pas trop tout retrouver dans un switch ).
    L'évènement est levé pour une liste d'éléments et non un élément afin d'optimiser le côté performance.
    Et oui, l'évènement est levé avant la suppression car j'avais besoin d'accéder à son contenu (c'est juste un choix lors de l'écriture, je sais qu'on a accès aux éléments supprimés d'une ObservableCollection via e.OldItems).

    Bref, par rapport au besoin, je trouvais cette méthodologie plus propre.

    S'il y a des avis contraires ou nuancés, je suis tout ouïe voire je serai ravi de les lire (il faut toujours sortir de sa tour d'ivoire ).
    --
    Arnaud DANEELS

  5. #5
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 749
    Points
    39 749
    Par défaut
    Disons que ton implémentation a un défaut un peu gênant...

    Si je fais ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    List<string> list = new ListTrigerred<string>();
     
    ...
     
    list.RemoveAll(s => s.StartsWith("a"));
    Ton évènement ne sera pas déclenché, car la méthode List<T>.RemoveAll n'est pas virtuelle, donc la méthode ListTrigerred<T>.RemoveAll ne fait que la masquer et ne participe pas au polymorphisme. Tu es donc obligé de savoir, au niveau où tu vas appeler RemoveAll, que tu as à faire à une ListTriggered<T> et non à une List<T>, ce qui n'est pas forcément une bonne chose car en général il vaut mieux essayer de faire abstraction du type concret. Cela dit, vu que de toutes façons RemoveAll n'est définie dans aucune interface mais seulement dans la classe List<T>, le problème existait déjà à la base...

Discussions similaires

  1. [VB.NET] datagrid & textbox/liste déroulante
    Par t1marlartiste dans le forum ASP.NET
    Réponses: 13
    Dernier message: 14/06/2007, 15h27
  2. [VB.NET] [VS 2003] Liste des objets instanciés
    Par Mouse dans le forum VB.NET
    Réponses: 4
    Dernier message: 23/10/2006, 19h15
  3. [C#][VB.Net]Récupérer la liste des dataadapter d'une form
    Par Sonny dans le forum Windows Forms
    Réponses: 12
    Dernier message: 11/01/2006, 20h13

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