begin process at 2012 02 11 18:03:15
  Trouver un code source :
 
dans
 
Accueil > 

Tutoriels

 > 

.NET

 > CRÉER SES PROPRES CLASSES GÉNÉRIQUES

CRÉER SES PROPRES CLASSES GÉNÉRIQUES


 Information sur le tutoriel

Déposé par rm50 le 16/03/2009 16:54:54
Dans la catégorie .NETTutoriel .NET ( DotNet )
Vu : 7 150 fois
 

Ecrire un message privé à l'auteur
Commentaire sur cette source (2)
Ajouter un commentaire et/ou une note

Note :
Aucune note

 Description

Le framework .NET propose toute une panoplie de classes dites génériques.
L'exemple le plus connu est probablement les List<type> qui permettent de créer des listes fortement typées.

Ce mécanisme est puissant, et nous pouvons nous aussi définir des classes génériques dans nos développements.

Mais qu'est ce qu'une classe générique ?

Tutorial

Créer ses propres classes génériques


Introduction


Le framework .NET propose toute une panoplie de classes dites génériques.
L’exemple le plus connu est probablement les List<type> qui permettent de créer des listes fortement typées.

Ce mécanisme est puissant, et nous pouvons nous aussi définir des classes génériques dans nos développements.

Mais qu’est ce qu’une classe générique ?

En fait, une classe générique est un Template (modèle) de comportements que je peux appliquer à de multiples situations, sur de multiples objets.

Pour expliquer cela, nous nous baserons sur un exemple simple, tout au long du tuto.

Contexte de base

Je travaille dans une entreprise qui fabrique des véhicules à moteur. Véhicules pour lesquels toutes les associations sont possibles ! (tous les châssis peuvent accueillir tous les moteurs, et tous les modèles de roues).

Ajoutons que je suis fainéant, et que je n’ai pas envie de ré écrire l’entièreté de la définition d’un véhicule à chaque modèle que je dois créer (ou chaque association possible),
Néanmoins, je dois contrôler, la définition des associations (moteur, châssis, roues).

Pourquoi ne pas créer un Template de voiture ? Telle est la question du jour…

Pour ce faire, il me faut penser de la façon suivante :

Quels sont les comportements similaires ?

Un véhicule peut :

  • Rouler,
  • Klaxonner,
  • Se comporter sur la route,

A partir ce cela, je sais ce qui sera implémenté de façon commune…

Ma classe générique se bornant à effectuer les appels aux types manipulés (appeler le moteur, les roues et le châssis si nécessaire).


Définition de base de ma classe véhicule…

Notons la syntaxe suivante :

public class Vehicule <ClassChassis, ClassMoteur, ClassRoues>


Elle définit trois types manipulés par ma classe Vehicule…


Rapidement deux problèmes se présentent :

  • Une erreur du compilateur : je ne peux pas instancier de valeur dans le constructeur pour les types déclarés,
  • Je ne connais pas les opérations accessibles pour les types définis, et donc, je ne peux pas utiliser leurs comportements…
  • ClassChassis
  • ClassMoteur
  • ClassRoues


Les contraintes de type


Pour palier à cela, nous allons préciser les types génériques déclarés par des clauses de précision (comme en SQL, lorsque nous filtrons avec une clause where).


En .NET cette notion de précision se présente comme des contraintes de type.


Ces contraintes se déclarent juste après la déclaration de la classe, suivant le canevas suivant :
    where <type> : contrainte [,contrainte]


Nous verrons la liste des contraintes possibles juste après notre exemple,
Dans notre code cela donne :

    Ci dessus, la contrainte nous informe que les types :

  • ClassChassis
  • ClassMoteur
  • ClassRoues

disposent d’un constructeur vide.

Cela me permet de pouvoir instancier dans le constructeur les instances de moteur, châssis et roues.


Les contraintes possibles sont les suivantes :

(D’après : http://msdn.microsoft.com/fr-fr/library/d5x73970(VS.80).aspx)

where T : struct


L'argument de type T doit être un type valeur, non nullable, (System.Int32, … ou une structure définie dans le code), le type System.String n’est pas admis car il peut prendre null comme valeur.

where T : class


L'argument de type T doit être un type référence, une classe.

where T : new()


L'argument de type T doit avoir un constructeur vide, si plusieurs contraintes sont définies, celle ci doit être la dernière.

where T : <className>


L'argument de type T doit être de type <ClassName>, ou en dériver, où <ClassName> est également un type générique.


Exemple :
public class Gen<T1, T1parent>
where T1 : T1parent


where T : <InterfaceName>


L'argument de type T doit implémenter l’interface <InterfaceName>

where T : ClassName


L'argument de type T doit être de type ClassName, ou en dériver.


Revenons à notre exemple, nous avons besoin de connaître les membres manipulables dans notre classe générique, dès lors, il nous faut définir des Interfaces qu’implémentent mes classes (Roues, Moteur et Châssis). Il m’est également possible de définir des classes qu’héritent mes classes (abstraites ou non), suivant le contexte.

Pour ce faire, et parce que je suis propre dans mes architectures, je vais créer un autre assembly, qui ne contient que les interfaces de mes objets. Dans ce dernier, je vais définit trois interfaces :

  • IMoteur,
  • IRoue,
  • IChassis,

Je vais me servir de ces définitions pour pouvoir manipuler mes types au sein de ma classe générique.


    IMoteur définit les méthodes et propriétés suivantes :

    

<<Interface>>
IMoteur

+ Cylindree : Int32
+ Puissance : Int32
+ Couple : Int32

+ RapportEngagé : Int32

+ MonteRegime ( ) : String
+ ChangeRapportBoite (monteDescend : bool) : String


    IRoue définit les méthodes et propriétés suivantes :

    

<<Interface>>
IRoue

+ NomModele : String
+ Taille

+ Tourne (vitesse : Int32) : String


    IChassis définit les méthodes et propriétés suivantes :

    

    

<<Interface>>
IChassis

+ NomModele : String

+ Comportement (typeRoute : String) : String


La définition de ma classe prendra cette syntaxe :

Notons :

  • L’ajout d’une instruction using pointant vers l’assembly qui contient les interfaces,
  • L’ajout des contraintes forçant / définissant les interfaces implémentées par les types,
  • L’ordre des contraintes : la directive « constructeur vide » (new ( ) ) est toujours la dernière.


Implémentation d’une méthode de la classe générique : Roule ( )


Dès lors que je connais les membres manipulés (par leur Interface), je peux implémenter de façon générique les comportements de ma classe véhicule.



Il me reste plus qu’à déclarer des classes qui implémentent mes interfaces, et à instancier une classe Vehicule (ou une classe qui hérite d’un véhicule) pour pouvoir l’utiliser.

Exemple de syntaxe :


Classe déclarée et instanciée :

Vehicule <ChassisUtilitaire, MoteurSimple, RoueJanteAcier>
    vehicule = new Classes.Vehicule

< ChassisUtilitaire,

MoteurSimple,

RoueJanteAcier>();

Classe dérivée :


public class VehiculeUtilitaire :
    Vehicule<ChassisUtilitaire,MoteurSimple,RoueJanteAcier>

{


    }


Exemple réel

Il m’a été demandé un jour de concevoir un mécanisme de DAL (data access layer), mais qui permet de ne plus rédiger une seule ligne de code, tout en disposant du mécanisme d’accès aux données et de mapping relationnel objet.


En gros ce mécanisme générique permet d’automatiser la génération des requêtes vers une base de données SQL CE pour les opérations suivantes :

  • Création de la table,
  • Insertion de données,
  • Update de données,
  • Select all
  • Select en fonction de critères (gérés dynamiquement).


Une sorte de framework comme Ibatis mais sans la complexité de paramétrage XML.


Son mécanisme repose sur deux principes :

  • Décoration des classes à manipuler par des System.Attributes « maison »,
    La classe générique peut ainsi se baser sur ces attributes pour disposer des informations permettant de manipuler la base de données en lien avec les classes,
  • Les types à spécifier pour la classe générique sont :
  • Le type de l’objet à manipuler,
  • Le type qui permet de disposer des éléments critères de recherche
  • Le type représentant une liste d’objet.


Cela fera l’objet d’un autre tuto…


Remarque

L’exemple est implémenté dans l’archive auto extractable http://www.csharpfr.com/codes/EXEMPLE-LIE-TUTO-CREER-PROPRES-CLASSES-GENERIQUES_49513.aspx

Elle contient 4 Assembly (projets)

  • BDV.Exemple.Generique
    Contient une application Winform exécutant l’exemple,
  • BDV.Exemple.Generique.Classes
    Contient la classe générique
  • BDV.Exemple.Generique.Classes.Metier
    Contient les classes métier (Roue, moteur, châssis)
  • BDV.Exemple.Generique.Interfaces
    Contient les Interfaces (IRoue, IMoteur, IChassis)

 Historique

16 mars 2009 17:10:43 :
style
16 mars 2009 17:12:41 :
style
16 mars 2009 17:21:28 :
Ajout lien vers les sources
16 mars 2009 17:23:06 :
Ajout exemple
16 mars 2009 17:24:18 :
aj source
16 mars 2009 17:26:27 :
style
16 mars 2009 17:28:22 :
style
16 mars 2009 21:36:13 :
lien source
16 mars 2009 21:57:43 :
Pb liens vers source
16 mars 2009 22:05:32 :
style
16 mars 2009 22:09:18 :
style
16 mars 2009 22:10:42 :
ok
16 mars 2009 22:18:37 :
s
16 mars 2009 22:38:09 :
pb look

Commentaires

Commentaire de claudetom le 16/03/2009 21:47:30

Très bon Tuto,
Explications et mise en oeuvre.

Commentaire de istamkenitra le 21/03/2009 13:02:06

Rien à dire à part chapeau :)
vous avez répondus à beaucoup de question je me posais à propos de la généricité.

NB :

Pour les Développeur VB.Net ce site : http://www.developerfusion.com/tools/convert/csharp-to-vb/
pourra vous servir a bien comprendre le tutoriel ;) Bonne chance
Merci rm50

 Ajouter un commentaire




Nos sponsors


Sondage...

CalendriCode

Février 2012
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
272829    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 15,959 sec (4)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales