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

billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 - 12 févr. 2009 à 11:36
billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 - 16 févr. 2009 à 09:24
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

Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 42
13 févr. 2009 à 02:13
Salut, c'est pas bien clair, essaye de formuler ta question autrement stp ; )
0
billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 29
13 févr. 2009 à 09:21
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
---------------------
0
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 42
13 févr. 2009 à 09:55
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" );
    }
}
0
billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 29
13 févr. 2009 à 10:27
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
---------------------
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
WishhhMaster Messages postés 327 Date d'inscription mardi 17 février 2004 Statut Membre Dernière intervention 10 avril 2010 8
13 févr. 2009 à 11:12
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.
0
WishhhMaster Messages postés 327 Date d'inscription mardi 17 février 2004 Statut Membre Dernière intervention 10 avril 2010 8
13 févr. 2009 à 11:13
J'ai oublié le lien lol.
0
billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 29
13 févr. 2009 à 11:27
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
---------------------
0
titeoe Messages postés 433 Date d'inscription samedi 26 avril 2003 Statut Membre Dernière intervention 4 décembre 2009 1
16 févr. 2009 à 08:57
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.
0
billou_13 Messages postés 860 Date d'inscription jeudi 4 mars 2004 Statut Membre Dernière intervention 19 août 2014 29
16 févr. 2009 à 09:24
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
---------------------
0