2010-06-16 2 views
5

J'ai quelques classes héritent de Windows existant contrôles comme TextBox et DateTimePicker, ..etcQuelle est la meilleure pratique pour une solution alternative de multi-héritage en C#

Je veux ajouter des fonctionnalités personnalisées pour ces classes comme (Read, Alert, ... etc) ces fonctionnalités ajoutées sont les mêmes dans toutes ces classes

le problème est: ces classes héritées des parents de différence, donc je ne peux pas mettre mes fonctionnalités ajoutées dans la classe parente,

Quelle est la meilleure pratique dans ce cas:

  • Répétez le code dans chaque classe héritée

  • Utiliser une classe séparée ont les fonctionnalités que les méthodes statiques avec le paramètre d'une interface, implémenter cette interface pour les classes et les passent ensuite.

  • Utilisez une classe comme la deuxième séparée approche, mais avec le paramètre dynamique (qui a ajouté en C# 4,0)

    ou autre !!

Merci à l'avance

Répondre

12

Je considérerais l'option 4: composition.

D'abord, définissez votre ensemble de fonctionnalités. Nous supposerons que votre liste partielle est exclusive, donc "Lire" et "Alerte". Ensuite, créez une classe unique qui implémente cette fonctionnalité, quelque chose comme MyCommonControlBehaviors. Je préférerais que cette implémentation ne soit pas statique si possible, cependant, elle peut être générique.

public MyCommonControlBehaviors 
{ 
    public Whatever Read() { /* ... */ } 
    public void Alert() {} 
} 

En troisième lieu, la composition d'utilisation pour ajouter une instance de cette classe à chacun de vos types de contrôle personnalisés et d'exposer cette fonctionnalité grâce à votre contrôle personnalisé:

public class MyCustomControl 
{ 
    private MyCommonControlBehaviors common; // Composition 

    public Whatever Read() { return this.common.Read(); } 
    public void Alert() { this.common.Alert(); } 
} 

Selon les détails, vous pouvez faire preuve de créativité pour le degré nécessaire. Par exemple, peut-être que vos comportements personnalisés doivent interagir avec des données de contrôle privées. Dans ce cas, faites en sorte que votre contrôle implémente une interface commune à laquelle vos comportements habituels ont besoin.Passez ensuite le contrôle dans la classe de comportement sur la construction comme une instance de ICommonBehaviorHost:

public interface ICommonBehaviorHost 
{ 
    void Notify(); 
} 

public class MyCommonControlBehaviors 
{ 
    ICommonBehaviorHost hst = null; 

    public MyCommonControlBehaviors(ICommonBehaviorHost host) 
    { 
     this.hst = host; 
    } 

    public void Alert() { this.hst.Notify(); } // Calls back into the hosting control 
    // ... 
} 

public class MyCustomControl : ICommonBehaviorHost 
{ 
    private MyCommonControlBehaviors common = null; 

    public MyCustomControl() { common = new MyCommonControlBehaviors(this); } 
    public Whatever Read() { return this.common.Read(); } 
    public void Alert() { this.common.Alert(); } 

    void ICommonBehaviorHost.Notify() { /* called by this.common */ } 
} 
+4

et le coupler avec injection de dépendances pour minimiser le couplage de votre système ... –

+0

+1 @marc_s for truth. Il y a beaucoup de techniques supplémentaires qui peuvent être utilisées pour minimiser le couplage et ajouter de la capacité à cette approche. Une chose que j'ai faite dans le passé est de rendre MyCommonControlBehaviors générique afin qu'il puisse renvoyer un MyCustomControl, quel qu'il soit. (Dans cet exemple, cela n'a pas beaucoup de sens, mais dans le domaine avec lequel je travaillais, cela avait beaucoup de sens.) –

1

Si vous le devez, ce que je ferais probablement est de créer des méthodes d'extension pour chaque classe, puis de référencer le codage réel nécessaire pour celles-ci dans un autre objet que toutes les méthodes d'extension peuvent appeler. De cette façon, le code n'est pas dupliqué et les méthodes d'extension donnent l'impression que les méthodes doivent être dans l'objet.

Il est essentiellement la même en créant une méthode statique et faire: Functions.DoSomething(my_Object);

Mais j'aime toujours: my_Object.DoSomething() mieux dans un langage OO.

0

je suggère de définir une interface pour les comportements, et (pour éviter de vous répéter) créer des méthodes d'extension sur cette définition d'interface pour vos méthodes partagées. (Un peu comme votre deuxième option, seulement avec des méthodes d'extension au lieu de méthodes totalement statiques).