Evénement à l'accession d'une classe [avec héritage]

Signaler
Messages postés
860
Date d'inscription
jeudi 4 mars 2004
Statut
Membre
Dernière intervention
19 août 2014
-
Messages postés
860
Date d'inscription
jeudi 4 mars 2004
Statut
Membre
Dernière intervention
19 août 2014
-
Bonjour,

Je suis confronté à un petit problème et j'aimerais bien savoir s'il existe une solution. Pour vous expliquer mon problème, voici un exemple:
public class A
{
  //...
}

public class B : A
{
  //...
}

Je voudrais, à chaque appel de l'objet B, lancé un process. Un peu comme ci on déclarer une méthode "TouchThis()" qui se déclenche à chaque fois que l'on fait appel à l'objet.
B.Do();//Lance implicitement la méthode TouchThis()
B.ReDo();//Lance implicitement la méthode TouchThis()

Je sais pour l'instant que je pourrais mettre A en tant que membre de B et mettre en place un accesseur à A qui lancera la méthode mais je suis un peu pro héritage et j'aime bien en faire quand le besoin y correspond. De plus, ce problème peut se poser dans une classe sans héritage. Donc, je fais appel à vous car je ne trouve rien.
J'aurai bien aimé un truc du style (propriété dans B):
public B this
{
  get { TouchThis(); return this; }
  set { TouchThis(); this = value; }
}
Mais le compilo à pas l'air d'aimer. Pourtant, moi, j'aimais bien ^^

Bonne journée,

Billou_13
Bask En Force

--------------------------------------------------------------------
Connaître la réponse est une chose, savoir pourquoi en est une autre
---------------------

9 réponses

Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
41
Salut, c'est pas bien clair, essaye de formuler ta question autrement stp ; )
Messages postés
860
Date d'inscription
jeudi 4 mars 2004
Statut
Membre
Dernière intervention
19 août 2014
26
Bonjour,

Je ne vois pas bien comment je pourrais être plus clair. Mon besoin personnel est le suivant (je vais faire un exemple sans héritage): j'ai une classe A qui a un membre privée "_lastUsed" (type: DateTime).
Exemple:

public class A
{
   private DateTime _lastUsed;

   public A()
   {
   }

   public void Do()
   {
   }

   public void ReDo()
   {
   }

   private void TouchThis()
   {
       _lastUsed = DateTime.Now;
   }
}

Je voudrais, qu'à chaque fois que je fais appel à un objet de type A, appeler implicitement (et non explicitement) la méthode "TouchThis()". Cela me permettra de savoir quand l'objet A a été utilisé par un process ?

Et là, vous allez me dire, pourquoi ne pas mettre "this.TouchThis();" dans le constructeur et les méthodes "Do()", "ReDo()" => tout simplement parce que dans mon cas A hérite d'une autre classe (ex: B) et que les méthodes de B ne peuvent appeler la méthode "this.TouchThis()". Je pourrais mettre en place des événements dans B pour dire que l'on a appelé une méthode mais imaginez jusqu'à quel point il faudrait descendre (sans oublier que l'appel à "ToString()" devra aussi appeler "TouchThis()").

---------------------

Alors pour l'instant, comme j'ai A (héritant de B) qui ne fait que ça, j'ai implementer la solution suivante:

public class A // : B , en commentaire car c'est cette solution que je cherche
{
   private B _b;
   private DateTime _lastUsed;

   public A()
   {
      B = new B();
   }

   public B B
   {
      get { this.TouchThis(); return _b; }
      set { this.TouchThis(); _b = value; }
   }

   private void TouchThis()
   {
      _lastUsed = DateTime.Now;
   }
}

Ca marche mais j'aimerais que ça marche avec A héritant de B. Car dans mon cas, pour appeler les méthodes de B, il faut faire:
objA.B.Method();//alors que j'aimerais objA.Method() !

Bonne journée,

Billou_13
Bask En Force

--------------------------------------------------------------------
Connaître la réponse est une chose, savoir pourquoi en est une autre
---------------------
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
41
Je ne suis toujours pas sûre de comprendre.. dis moi si ça t'aide :

public abstract class A
{
    protected abstract void Touch( );


    public void MethodeNonVirtuelle( )
    {
        Touch( );
        MessageBox.Show( "Methode Non Virtuelle de A" );
    }


    public virtual void MethodeVirtuelle( )
    {
        Touch( );
        MessageBox.Show( "Methode Virtuelle de A" );
    }
}


public sealed class B : A
{
    private DateTime dt;


    protected override sealed void Touch( )
    {
        dt = DateTime.Now;
        MessageBox.Show( dt.ToLongTimeString( ) );
    }


    public new void MethodeNonVirtuelle( )
    {
        Touch( );
        MessageBox.Show( "Methode Non Virtuelle de B" );
    }


    public override sealed void MethodeVirtuelle( )
    {
        Touch( );
        MessageBox.Show( "Methode Virtuelle de B" );
    }
}
Messages postés
860
Date d'inscription
jeudi 4 mars 2004
Statut
Membre
Dernière intervention
19 août 2014
26
Lutinore,

Merci pour ta réponse. Cependant, dans ton cas, il s'agit d'un appel explicite (et non implicite). De plus, dans ton exemple, comment appelles-tu la méthode Touch() lorsque la méthode ToString() sera appelée ?
En faisant un new:
public new string ToString()
{
   Touch();
   return base.ToString();
}
//Pas terrible quand même ^^ de devoir implémenter toutes les méthodes.

Je cherche donc un appel implicite. J'avoue que je pense que la solution n'existe pas mais je poste au cas où ^^

Bonne journée,

Billou_13
Bask En Force

--------------------------------------------------------------------
Connaître la réponse est une chose, savoir pourquoi en est une autre
---------------------
Messages postés
327
Date d'inscription
mardi 17 février 2004
Statut
Membre
Dernière intervention
10 avril 2010
8
Salut,

Regarde ce post (le dernier message correspond sans doute à ce que tu veux). Mais bon, ça t'oblige à utiliser la réflexion, donc pas très pratique et beaucoup plus lent.
Messages postés
327
Date d'inscription
mardi 17 février 2004
Statut
Membre
Dernière intervention
10 avril 2010
8
J'ai oublié le lien lol.
Messages postés
860
Date d'inscription
jeudi 4 mars 2004
Statut
Membre
Dernière intervention
19 août 2014
26
Effectivement, on vient de me parler du "ContextBoundObject" qui est intéressant pour du Trace mais dans mon cas, l'implémentation sera un peu lourde pour un besoin aussi simple.
Résultat: je vais garder la méthode que j'ai exposé.

Merci beaucoup à vous deux,

Billou_13
Bask En Force

--------------------------------------------------------------------
Connaître la réponse est une chose, savoir pourquoi en est une autre
---------------------
Messages postés
433
Date d'inscription
samedi 26 avril 2003
Statut
Membre
Dernière intervention
4 décembre 2009
1
Bonjour,

Juste comme ça, sans tester, deux idée me viennent :

Simplement : Tu créée une classe de base abstraite avec un évènement ChildTouched.
Sur chaque accesseur que tu veux surveiller, tu déclenches l'évènement de la classe.

Ce qui donne :
public abstract BaseClass {...}
public A : BaseClass {...}
public B : A {...}

Ensuite, il te reste à t'abonner à l'evenement de BaseClass.


Un peu plus compliqué : Tu peux utiliser de l'AOP pour injecter du code sur tes accesseurs de B. Dans ce cas ce site t'aidera : http://www.postsharp.org/

Bon courage.
Messages postés
860
Date d'inscription
jeudi 4 mars 2004
Statut
Membre
Dernière intervention
19 août 2014
26
Bonjour,

Merci titeoe pour ta réponse. Pour ta première idée, elle ne résout pas la problème que j'avais soulevé à Lutinore:
"De plus, dans ton exemple, comment appelles-tu la méthode Touch() lorsque la méthode ToString() sera appelée ?
En faisant un new:
public new string ToString()
{
   Touch();
   return base.ToString();
}
//Pas terrible quand même ^^ de devoir implémenter toutes les méthodes."

Pour ta deuxième idée: utilisation de PostSharp, j'avais effectivement trouvé cette idée dans le lien de WishhhMaster. Cette idée se revèle trop lourde pour mon besoin aussi simple.
Je vais donc rester sur ma première idée ^^ (espérons que le C# 5.0 ajoutera une telle fonctionnalité ^^).

Bonne journée à tous et merci encore,

Billou_13
Bask En Force

--------------------------------------------------------------------
Connaître la réponse est une chose, savoir pourquoi en est une autre
---------------------