Professional Documents
Culture Documents
La technologie .NET
Par : Karim Kalti
SOMMAIRE
Introduction la technologie .NET Le Langage C#.NET Les IHM en .NET Accs aux donnes (ADO.NET) Architectures des applications Web dynamiques ASP.NET Les services Web Les serveurs de mdia (audio et vido streaming) Dveloppement et dploiement d'applications Web multimdia.
V - 3.1
Karim Kalti
Exemple : //// VB.NET //// Dim i as Integer i=5 Console.WriteLine(i) //// C++.NET //// int i; i=5; Console::WriteLine(i); //// C#.NET //// int i; i=5; Console.WriteLine(i); Cet exemple montre que chacun des trois langages utilise sa propre syntaxe pour la dclaration des variables, mais les trois font appel la mme mthode .NET pour faire l'affichage bien sr chacun avec ses propres rgles d'criture.
Karim Kalti
La bibliothque .NET est constitue de trois couches de classes offrant trois catgories de services : Premire couche : Base classes Library (BCL) La BCL rassemble des classes permettant d'effectuer les oprations de base telles que la manipulation de chanes de texte, la gestion des entres/sorties, des communications rseaux, des threads, etc.
Deuxime couche : les classes de donnes et XML La deuxime couche est compose de deux bibliothques de classes d'accs aux donnes : La bibliothque ADO.NET, s'levant sur les bases de l'ancien ADO (ActiveX Data Objects) et permettant l'accs sous format XML aux interfaces de bases de donnes SQL Server ODBC, OLEDB, ORACLE, et aux fichiers XML. Une bibliothque de classes permettant de manipuler les donnes XML. On y trouve par exemple les classes XSLT permettant la transformation d'un document XML vers n'importe quel type d'autre document.
Troisime couche : les services Web, les applications Web et les applications Windows La dernire couche, la plus leve, est utilise pour la cration des applications Web et des applications Windows et notamment la partie interface : Les applications Web peuvent se prsenter sous formes de pages Web dynamiques et statiques ou sous forme de services Web. La technologie utilise pour leur cration est l'ASP.NET. Elle utilise pour la ralisation des interfaces de nouveaux composants appels les WebForms. Les applications Windows et particulirement leurs interfaces sont cres l'aide des WinForms.
System.Web
Services Description Discovery Protocols Caching Configuration UI HtmlControls WebControls Form
System.Windows.Forms
Button ListControl MessageBox
System.Drawing
Security SessionState Drawing2D Imaging Printing Text
System.Data
OLEDB Design SQL SQLTypes XSLT XPath
System.Xml
Serialization
System
Collections Configuration Diagnostics Globalization IO Net Reflection Resources Security ServiceProcess Text Threading Runtime InteropServices Remoting Serialization
Karim Kalti
Les classes de la bibliothque .NET sont organises sous forme d'espaces de noms hirarchiss. Chaque espace de noms peut comporter un ensemble de classes et/ou un ensemble de sous-espaces de noms. L'accs une classe s'effectue l'aide son nom complet. Ce nom complet se compose de la liste hirarchique des espaces de noms plus le nom de la classe en question. Ces noms tant relis entre eux par des points. Exemple : La classe DataSet qui se trouve dans l'espace de noms "System.Data.ADO" se dclare comme "System.Data.ADO.Dataset". La classe Console qui se trouve dans l'espace de noms "System" se dclare comme "System.Console".
Le MSIL
La compilation d'un programme crit en .NET conduit vers la cration d'un fichier excutable (fichier .exe). Cet excutable n'est pas crit en code machine comme les excutables classiques mais avec un langage intermdiaire appel MSIL acronyme de MicroSoft Intermediate Language. L'excution des fichiers compils en MSIL ne peut pas tre directement assure par les services du systme d'exploitation.
L'assemblage
L'assemblage est le fichier exe ou dll produit par la compilation d'un code .NET. Un assemblage contient trois types de donnes : o Le code MSIL qui rsulte de la compilation. o Les mta donnes. o Les ressources.
MSIL dans un assembly Un code .NET peut comporter plusieurs classes. Au moment de la compilation, toutes ces classes sont compiles en MSIL dans un mme assemblage. Les classes d'un mme assemblage doivent avoir un seul point d'entre (Une seule classe parmi celles d'un assemblage doit avoir une mthode qui joue le rle de fonction principale). Il est rappeler que le point d'entre est dfini par la mthode Main pour les applications de type console, par la mthode WinMain pour les applications Windows et par DllMain pour les dll (Dynamic Linked Library).
Karim Kalti
Les mta donnes Les donnes qui accompagnent le code MSIL dans un assemblage sont de deux catgories : Des donnes de description des types : les types sont les classes compiles dans l'assemblage. La description concerne alors les spcifications de ces classes (noms, attributs, mthodes, droits d'accs, interfaces implmentes, ). Ces informations sont gnralement utilises par les EDI pour la compltion de code. L'assembly manifest : Le manifeste contient des informations du genre : o Nom : le nom de l'assemblage. Il sert la rsolution de porte. Il est le mme que celui du fichier de l'assemblage moins l'extension. o Version : la version de l'assemblage. o Culture : permet d'indiquer le type de ressource utiliser en ce qui concerne la culture (langue, criture de droite gauche, type de calendrier ). o Autres assemblages : les assemblages ncessaires l'excution de l'assemblage courant. Ces assemblages sont gnralement des dlls. Les ressources Les ventuelles ressources utilises par l'assemblages : icnes, bitmap,
Un programme manag (Managed program) est un programme compil en MSIL, son excution est gre par la CLR. Un programme non manag est un programme compil en code natif. Son excution est directement prise en charge par les services du systme d'exploitation. VB.NET et C#.NET ne permettent de crer que des programmes manags. C++.NET permet de crer des programmes manags et non manags.
Karim Kalti
Avantages de la CLR
Scurit de l'excution des programmes. Grce la gestion des exceptions et la gestion automatique de la mmoire. Interoprabilit de programmes crits dans diffrents langages. Tous les langages qui supportent le .NET compilent vers un mme code intermdiaire Possibilit de faire communiquer des programmes crits dans des langages diffrents.
Portabilit des programmes Etapes de gnration d'un programme excutable : Fichier source (C#.NET) Compilation Fichier source (exemple C++) Compilation + Edition des liens
Excutable spcifique un systme d'exploitation donn et un p donn.
Interprtation
Interprtation
Interprtation
Excution
OS
Karim Kalti
Au moment de l'excution, la CLR assure entre autres la compilation Just In Time (JIT) du MSIL vers le code natif qui tient compte des services de la plateforme de destination. Il existe plusieurs versions de la CLR, chacune est spcifique une plateforme donne. Ce sont ces versions qui assurent la portabilit des excutables .NET (assemblies) Comparaison entre .net et Java :
.NET
Code source MS Intermediate Langage CLR
JAVA
Code source Bytecode Machine virtuelle (JVM)
.NET FrameWork en tant que spcification est une spcification publique (propose par MS). Il existe deux principales implmentations de cette spcification. o Implmentation propose par MS : destine aux plate-formes 2000,XP, 2003 server. o Projet Mono : implmentation destine tourner sous Linux (CLR pour Linux).
Qu'est ce qu'un environnement de Dveloppement Intgr (EDI) Un environnement de dveloppement intgr (EDI) est un outil qui facilite et acclre le dveloppement d'applications. Il intgre les modules ncessaires pour le dveloppement d'applications : o Editeur de code avec coloration syntaxique et compltion de code. o Lancement des processus de compilation et d'excution travers des menus sans passer en mode ligne de commande. o Outils de dboguage ... o Certains environnements de dveloppement intgrent des fonctionnalits de type RAD (Rapid Application Developpment). Ces fonctionnalits permettent de crer d'une manire visuelle une grande partie de l'application ( l'aide d'assistants WYSIWYG) et gnrent automatiquement le code correspondant.
EDI gratuit SharpDevelop : pour developper des applications windows et mobiles. (EDI seulement) WebMatrix : pour developper des applications Web. (EDI seulement) 7
Karim Kalti
Ordre d'installation des composants : CLR (si elle n'est pas installe par dfaut sur le systme). IIS. MDAC. .NET FrameWork. EDI.
Pour VisualStudio.NET : l'installation de ces diffrents composants se fait d'une manire automatique.
Karim Kalti
Caractristiques et nouveauts
C# : se prsente comme la suite des langages C et C++, trs proche de JAVA. Langage compltement orient objet pas de possibilit dcrire des fonctions en dehors des classes, pas de variables globales. Permet lcriture des programmes plus surs et plus stables grce la gestion automatique de la mmoire laide du ramasse miette (garbage collector) et la gestion des exceptions. Nouveauts par rapport au C++ : o Libration automatique des objets. o Disparition des pointeurs. (remplacs par des rfrences). o Disparition du passage d'argument par adresse au profit du passage par rfrence. o Nouvelles manipulations des tableaux. o Nouvelle manire d'crire les boucles. (foreach) o Disparition de l'hritage multiple mais possibilit d'implmenter plusieurs interfaces par une mme classe.
Premier programme
using System ; class Prog { static void Main() { Console.WriteLine(Bonjour); } }
Un programme C# comporte obligatoirement une fonction Main (M majuscule). Main doit tre obligatoirement membre dune classe. Le point virgule la fin de la dfinition dune classe est optionnel (pas en C++). Pou afficher le message bonjour on utilise la mthode WriteLine de la classe Console. La classe Console fait partie de lespace de noms (bibliothque) System. La mthode WriteLine peut tre appele de deux manires : o Spcification du nom complet : System.Console.WriteLine o Spcification du nom relatif
Les commentaires en C#
Trois types de commentaires peuvent tre utiliss en C# : // /* */ /// Le reste de la ligne est considr comme commentaire. (commentaire ligne) Tout ce qui se situe entre les deux dlimiteurs est considr comme commentaire. (commentaire multi-lignes) Le reste de la ligne est considr comme commentaire servant la documentation automatique du programme. (commentaire de documentation)
Karim Kalti
Les identificateurs en C#
Premier caractre : lettre (y compris celles accentues) ou le underscore _ Distinction entre minuscule et majuscule. Les caractres accentus sont accepts. Un mot rserv du C# peut tre utilis comme identificateur de variable condition quil soit prcd de @. NbLignes, Nbcoles, @int
Exemples didentificateurs :
Les instructions du C#
Une instruction se termine obligatoirement par un point virgule. Une suite d'instructions dlimites par des accolades constitue un bloc. Les blocs dfinissent les zones de validit des variables (porte des variables).
Mots rservs du C#
abstract as base bool break byte case catch char checked class const continue decimal default delegate do double else enum event explicit extern false finally fixed float for foreach goto if implicit in int interface internal is lock long namespace new null object operator out override params private protected public readonly ref return sbyte sealed short sizeof stackalloc static string struct switch this throw true try typeof uint ulong unchecked unsafe ushort using virtual volatile void while
Types de donnes
Les types du C# sont de deux catgories : les types "valeur" et les types "rfrence". Type "valeur" Une variable de type valeur est une variable auto au sens du C++. Elle est alloue sur la pile (stack). Sa dure de vie est gre par le systme (le runtime pour le C#). Type "rfrence" Une variable de type rfrence est une variable dynamique au sens du C++. Une telle variable rfrence un objet allou dans le tas manag. La variable elle mme est alloue sur la pile. La dure de vie de l'objet rfrenc par une telle variable est gre implicitement par le Garbage Collector. Les variables de type rfrence ne peuvent tre accdes que d'une manire indirecte ( travers la rfrence). Elles sont de ce fait moins rapides que les variables de type "valeur".
10
Karim Kalti
La tentative d'accs une rfrence invalide (non initialise par exemple) engendre la leve d'une exception au moment de l'excution. Comparaison de valeurs et comparaison de rfrences Une variable de type "rfrence" contient une rfrence des donnes stockes dans un objet. Deux variables de types rfrences peuvent donc rfrencer les mmes donnes. Dans ce cas, la modification de ces donnes travers l'une de ces deux rfrences affecte automatiquement l'autre rfrence. Une variable de type "valeur" possde sa propre copie des donnes qu'elle stocke. Deux variables de type "valeur" peuvent avoir les mmes donnes mais chacune possde sa propre copie distincte. Dans ce cas la modification de l'une des deux variables n'affecte pas l'autre. Types C# et types .NET Il existe pour la majorit des types natifs du C# des types correspondants en .NET. La majorit des types natifs du C# sont de type "valeur". Les types .NET quant eux, sont dfinis sous forme de classes et sont de ce fait de type "rfrence". (une classe dfinit toujurs un type rfrence en C#) Les types du C# ainsi que leurs types correspondants en .NET sont prsents dans les deux tableaux suivants : Type "valeur" en C# bool byte sbyte char decimal double float int uint long ulong short ushort Type .NET Framework System.Boolean System.Byte System.SByte System.Char System.Decimal System.Double System.Single System.Int32 System.UInt32 System.Int64 System.UInt64 System.Int16 System.UInt16 Type .NET Framework System.Object System.String
Type rfrence en C#
object string
En C/C++ une valeur nulle est value false et une valeur 0 est value true, ce nest plus le cas en C#, true est true et false est false. Le type decimal est utilis pour les oprations financires. Il permet une trs grande prcision mais les oprations avec ce type sont deux fois plus lentes que les types double ou float.
Les variables
Dclaration Type NomVariable; Toute variable doit tre dclare dans un bloc. Elle cesse dexister en dehors de ce bloc, (pas de variable globale). Toute variable de type scalaire natif doit avoir obligatoirement une valeur (le compilateur signale une erreur sinon). En l'absence d'une initialisation explicite les champs d'un objet sont implicitement initialiss par le compilateur (numrique 0 et chane ""). Ce n'est pas le cas pour les variables de type scalaire.
Les constantes en C#
Constante entire : int i = 10 ; Constante de type long (Ajout du suffixe L) : long Constante relle : double k = 20.5; Constante relle simple (ajout du suffixe f) : float
j = 10L ; v = 20.5f;
11
Karim Kalti
Constante relle grande prcision (ajout du suffixe M ou m) : decimal d=1.56M ou Constante caractre (entre deux simples quotes) : char c=A; Constante chane de caractres (entre deux doubles quotes) : string s="bonjour";
1.56m;
Les tableaux
Les tableaux en C# sont des types "rfrence". Dclaration et allocation Type[] Tab ; // Tab est une rfrence un tableau. Tab = new Type[Taille] ; // Allocation de lespace mmoire du tableau. Lespace mmoire du tableau est allou sur le tas (heap). Exemple :
int [] T ; // Dclaration d'une rfrence un tableau d'entiers. T=new int [3] ; // Cration effective du tableau ou galement : int [] T = new int [3] ;
Initialisation
float[] TF= {2.5f ,0.3f,5.9f} ; ou float[] TF= new float[]{2.5f ,0.3f,5.9f} ; string[] TS={ALI,Salah, Imed};
Les cellules d'un tableau non explicitement initialis sont automatiquement mises 0. Exemple :
int[] TI = new int [3];
Libration dun tableau La libration dun tableau se fait automatiquement par le ramasse-miettes. Un tableau cesse dexister : o Lorsquon quitte le bloc dans lequel il est dclar. o Lorsquon assigne une nouvelle zone (nouvelle valeur y compris null) la rfrence qui dsigne le tableau. Exemple :
int[] T={10,5,23} ; // dclaration et initialisation , allocation implicite sans new. ... T=new int[]{100,50,65,80} ou galement T=null ; // rallocation automatique de
La zone mmoire rserve aux 3 entiers prcdents est libre par le ramasse-miettes. Accs aux cellules dun tableau Syntaxe : Tab[indice] Pour un tableau de n lments, le premier lment a pour indice 0 et le dernier a pour indice n-1. Contrairement C/C++, il nest pas possible daccder un tableau en dehors de ses bornes. Ceci est signal comme une erreur. (leve d'exception)
12
Karim Kalti
Tableau plusieurs dimensions Exemple : Tableau deux dimensions Dclaration : Type[ , ] T = new Type[2,3] ; // 2 lignes et 3 colonnes Initialisation : Type[ , ] T = {{Val1, Val2, Val3},{ Val4, Val5, Val6}}; Accs : T[i,j] Exemple : Tableau 3 dimensions
Type[ , , ] T = new Type[Dim1, Dim2, Dim3]; T[i,j,k] = Valeur ;
100 ;
T2 fait rfrence la zone mmoire contenant le tableau de trois lments. La zone mmoire contenant les 100 cellules est signale " librer". Le ramasse-miettes (Garbage Collector) la librera lorsque un besoin en mmoire se manifestera. Pour faire rellement une copie de tableaux il faut procder comme suit : Utilisation de la mthode CopyTo
int [] T1 = {1,2,3} ; int [] T2= new int[100] ; T2= new int[T1.Lenght] ; // lespace de T1.CopyTo(T2,0) ; // fait la copie partir
Tableaux avec des cellules de types diffrents Il est possible de crer des tableaux ayant des cellules de types diffrents. Le type de base de ces tableaux doit tre le type object. Une cellule de type object peut recevoir une valeur de n'importe quel type. Exemple :
object[] T = new object[3] ; T[0] = 12 ; T[1] = 1.2 ; T[2]= "Bonjour";
Tableaux dchiquets Un tableau dchiquet est un tableau qui possde des composantes de dimensions irrgulires. Par exemple, pour les tableaux deux dimensions on parle de tableau dchiquet si chaque ligne possde un nombre diffrent de colonnes.
13
Karim Kalti
Exemple :
int[][] T ; T= new int[2][] ; T[0] = new int[3] ; T[0][0] =1 ; T[0][1]=2 ; T[0][2]=3 ; T[1] = new int[]{10,20,30,40} ;
Les tableaux dchiquets ne sont pas compatibles avec le .NET (ne sont pas CLS compliant). Ils sont plutt spcifiques au C#.
Saisie en mode console La saisie en mode console se fait essentiellement l'aide des mthodes Read et ReadLine de la classe Console. La mthode Read() lit un caractre partir du flux standard dentre. La mthode ReadLine() lit une chane partir du flux standard dentre. La valeur retourne est "null" si aucune donne na t saisie (lutilisateur tape directement ENTREE). ReadLine ne peut retourner que des chanes de caractres. Il faut par la suite faire les conversions explicites vers les types de destinations. Ces conversions se font laide de la mthode Parse membre des classes reprsentant les types de base. Exemple :
// Lecture dun entier string s = Console.ReadLine(); int i = Int32.Parse(s); // Lecture dun rel string s = Console.ReadLine(); double d = Double.Parse(s);
Les oprateurs
Oprateurs arithmtiques : + - / % * Pr-Post Incrmentation : ++, -Oprateurs logiques : <, <=, >, >=, = =, !=, !,&&, ||. Autres oprateurs : +=, -=, *=
Structures de contrle
Similarits par rapport au C++ if.. else : (identique qu'en C++)
14
Karim Kalti
switch : globalement, la mme syntaxe qu'en C++. Il existe toutefois deux diffrences : o La valeur tester peut tre, en plus des types entiers, de type string. o Il y a une diffrence au niveau du passage dun "case" un autre en cas dabsence de "break". for, while et do..while : (identique qu'en C++) Les instructions break, continue et goto : (identique qu'en C++) Diffrences par rapport au C++ Essentiellement au niveau de lvaluation des expressions :
C++ : if(i) C# : if(i!=0) C++ : if(!i) C# : if(i==0)
Nouvelle boucle : foreach Permet de parcourir les tableaux et les collections. Syntaxe :
Type[] Tab = new Type [Taille] ; foreach (Type Var in Tab) Bloc dinstructions
Remarque : Cette boucle ne peut tre utilise que pour lire les valeurs des lments d'un tableau. Elle ne permet pas d'effectuer des modifications du contenu d'un tableau. Exemple :
int [] TI = new int[]{15,30,45,60} ; foreach (int i in TI) Console.WriteLine(i); string[] TS={ "ALI", "SALAH","KAMEL"}; foreach(string s in TS) Console.WriteLine(s);
Les fonctions
Dclaration : Syntaxe : Globalement comme en C++. Pas de fichiers denttes contenant les dclarations des fonctions. Passage de paramtres : Pas de passage par adresse. Passage par valeur : comme en C++. Passage par rfrence : il existe une diffrence syntaxique par rapport au C++. Les tableaux et les objets sont toujours passs par rfrence. Les paramtres possdant les autres types (int, float, string, , struct) peuvent tre passs par valeur ou par rfrence.
15
Karim Kalti
} static void Main( ) {int a = 3; int b = 7; Console.WriteLine("Somme de a et b:"+Somme(a,b)); Console.WriteLine("Contenu du tableau"); AfficherTab(CrerTableau()); } }
Passage par rfrence Il remplace le passage par adresse du C++. Si le paramtre passer la fonction est de type "valeur" alors le passage de sa rfrence se fait l'aide du mot-cl ref comme suit : Dclaration : void f(ref Appel : f(ref Param) ; Exemple :
using System; class Prog { static void Permuter(ref int x, ref int y) { int temp; temp = x; x=y; y=temp; } static void AfficherValeurs(int a, int b) { Console.WriteLine("a :"+a); Console.WriteLine("b :"+b); } static void Main() { int a =5; int b =6; Permuter(ref a, ref b); AfficherValeurs(a,b); } } Type Param) ;
Une variable ayant un type rfrence (Exemple : tableau, objet d'une classe, ) passe par dfaut par rfrence lorsqu'elle est transmise comme paramtre une fonction. Le mot-cl ref n'est pas utilis dans ce cas. Passage darguments non initialiss Un argument pass l'aide du mot-cl ref doit tre obligatoirement initialis. En d'autres mots, il doit avoir ncessairement une valeur au moment de sa transmission la fonction lors de l'appel de cette dernire. Toutefois, plusieurs situations en programmation ncessitent l'utilisation d'arguments sans valeurs initiales. C'est le cas par exemple des fonctions qui ont besoin de retourner plusieurs valeurs. Ces valeurs ne peuvent pas tre renvoyes toutes par return. Elles peuvent plutt tre places dans des arguments qui sont passes par rfrence la fonction. Le passage d'arguments non initialises ne peut pas se faire avec ref. Il est fait plutt avec le mot-cl out. Un argument de type out est un paramtre qui passe par rfrence sans ncessiter toutefois d'tre initialis au moment de sa transmission. Un argument de type out est initialis par la fonction appele. Syntaxe : Dclaration : Type Fct(out TypeParam NomParam) Appel : Fct(out NomArgument) Exemple 1:
using System; class Prog { static void CalculerTriple(int x, out int triple) { triple = 3*x;} static void Main() { int x = 5;
16
Karim Kalti
Le paramtre triple n'a pas de valeur au moment de l'appel de la mthode CalculerTriple. Il prend sa valeur l'intrieur de cette dernire. C'est pourquoi il est pass l'aide de out. Exemple 2: Saisie d'un tableau
using System; class Prog { static void Saisie(out int[] Tab) { Tab = new int[3]; Tab[0]=21; Tab[1]=85; Tab[2]=5; }
Remarques : Une proprit de classe ne peut pas tre passe comme un argument de type ref ou de type out. La surcharge de mthodes est possible si les signatures de deux mthodes diffrent seulement par un ref ou seulement par un out. La surcharge n'est pas valide pour deux mthodes dont les signatures diffrent par ref et par out. Exemples: // Exemple de surcharge correcte car les deux signatures diffrent seulement par out
void f(int i){ } void f(out int i){ }
// Exemple de surcharge incorrecte car les deux signatures ne peuvent pas se distinguer par ref et out.
void g(ref int i){ } void g(out int i){ }
Les structures
Les structures constituent un moyen de construction de types personnaliss. Une structure permet de regrouper plusieurs champs dans une mme entit. Une structure est toujours de type valeur. Dclaration struct NomStructure { ModificateurAcces type1 champ1; ModificateurAcces type2 champ2; ModificateurAcces type3 champ3; } ModificateurAcces dsigne le modificateur de droit d'accs (public, private, internal). L'utilisation d'un point virgule la fin de la dclaration d'une structure est optionnelle. Exemple :
struct Pers { public string Nom; public int Age; }
17
Karim Kalti
Dclaration d'une variable de type structure Syntaxe : NomStructure NomVar; NomVar est une variable de type valeur. Exemple :
Pers P;
Accs aux champs Lorsqu'un champ d'une structure est publique alors il peut tre accd comme suit : NomVar.Champ; Exemple :
P.Nom = "Toto"; P.Age = 20;
Constructeur d'une structure Une structure peut avoir 0, un ou plusieurs constructeurs. Une structure ne peut pas avoir un constructeur par dfaut explicitement dfini. Le seul constructeur par dfaut accept est celui implicite. Ce dernier est automatiquement gnr mme si la structure comporte des constructeurs paramtrs explicitement dfinis. Le constructeur par dfaut d'une structure initialise automatiquement les champs numrique 0 et les champs de type chanes "". Un constructeur paramtr d'une structure doit obligatoirement initialiser tous les champs de la structure. (une initialisation partielle engendre une erreur). Exemple 1 :
struct Pers { public string Nom; public int Age; Pers(){Nom = Toto;Age=20;} // Erreur }
Exemple 2 :
struct Pers { public string Nom; public int Age; Pers(string N){Nom = N;} // Erreur }
Une structure ne peut pas hriter d'une classe ou d'une structure. Les variables structures peuvent galement tre dclares l'aide de new comme suit : Syntaxe : NomStructure NomVar = new NomStructure(); Exemple :
Pers P = new Pers();
Mais mme avec cette syntaxe, P reste une variable de type valeur. Cette syntaxe permet tout simplement d'appeler explicitement les constructeurs paramtrs chose qui n'est pas possible avec la premire criture.
Mthodes d'une structure Une structure peut avoir des mthodes. Ces dernires sont dclares l'intrieure de la structure.
Exemple :
using System; struct Pers { public string Nom; public int Age; public Pers(string N, int A){ Nom=N; Age=A;} public void Afficher() { Console.WriteLine("Nom :"+Nom+" Age : "+Age);} } class Prog { static void Main() { Pers P = new Pers("Ali",20); P.Afficher(); }
18
Karim Kalti
Remarque : En C#, tous les types de donnes scalaires tels que int, float, double, sont implments sous forme de structures intgres. Exemple :
int int int int i = 5; j = new int(5); // initialisation de j 5. k = new int(); // initialisation automatique de k zro. L; // L n'est pas initialis.
Les numrations
Une numration est un outil permettant de construire un type ayant un ensemble fini de valeurs. Une numration dfinit toujours un type valeur. Dclaration : enum NomEnumeration {Valeur1, Valeur2, , ValeurN};
Les valeurs d'une numration sont codes comme des entiers de type int. Dans ce cadre Valeur1 vaut par dfaut 0, Valeur2 vaut 1 et ainsi de suite. Il est possible d'attribuer d'une manire explicite d'autres constantes entires aux valeurs d'une numration comme suit : enum NomEnumeration {Valeur1=20, Valeur2=65, , ValeurN}; Accs aux valeurs d'une numration Syntaxe : NomEnumration.Valeur Dclaration d'une variable de type numration Syntaxe : NomEnumration Var; Affectation de valeur Syntaxe : Var = NomEnumration.Valeur; Une variable numration est toujours de type "valeur". Exemple :
using System; enum Couleur {Rouge, Orang, Vert}; class Prog { static void Message(Couleur Feu) { switch (Feu) { case Couleur.Vert : Console.WriteLine("Vous pouvez passer"); break; case Couleur.Orang : Console.WriteLine("Prparez vous vous arrter"); break; case Couleur.Rouge : Console.WriteLine("Arrtez immdiatement"); break; } } static void Main() { Couleur Feu; Feu = Couleur.Vert; Message(Feu); } }
19
Karim Kalti
La conversion de donnes
Conversion implicite Certaines conversions sont effectues implicitement par le compilateur car de par leur sens et les types qu'elles font intervenir elles ne peuvent jamais engendrer des erreurs ou des pertes de donnes. Exemple:
int a=5; long b=a;
Conversion explicite Certaines conversions peuvent ne pas tre sres. Il incombe alors au programmeur de les faire explicitement s'il en a besoin. Ces conversions ne mnent pas toujours vers un rsultat correct. Syntaxe : Type1 Var1; Type2 Var2 = (Type2) Var1; Exemple :
long a=5; int b= (int)a;
Si a est dans la plage de valeur du type int alors la conversion est accepte. En cas de dpassement de capacit, la conversion sera refuse et une exception de type System.OverflowException sera leve. Conversion entre types "rfrence" Pour les objets la conversion n'est dfinie qu'entre un objet parent et un objet enfant. Elle se fait : D'une manire implicite d'un objet enfant vers un objet parent. Elle doit tre effectue d'une manire explicite dans le sens contraire (parent-enfant). Aucune vrification n'est effectue au moment de la compilation. Si une perte de donnes peut tre cause alors la conversion est annule et une exception de type System.InvalidCastException est leve. Syntaxe : TypeParent Var1; TypeEnfant Var2 = (TypeEnfant) Var1;
Le boxing et le unboxing
Le boxing Le boxing consiste convertir une variable de type "valeur" en une rfrence de type System.Object. Le boxing peut se faire d'une manire implicite ou explicite: Syntaxe : TypeValeur Var; Object box = Var; // Boxing implicite Object box = (Object) Var; // Boxing explicite Exemple1 :
int i =123; Object box =(object)i; // boxing explicite
Exemple 2 : Un des prototypes de WriteLine est le suivant : void WriteLine(Object); L'appel suivant de cette mthode est rendu possible grce au boxing implicite :
int n=5; Console.WriteLine(n); // boxing de int dans object
20
Karim Kalti
Le unboxing Le unboxing est l'opration inverse du boxing. Il consiste convertir une rfrence de type System.Object vers une variable de type "valeur". Le unboxing ne peut se faire que d'une manire explicite. Syntaxe :
Object box; TypeValeur Var = (TypeValeur) box; // La conversion n'est pas toujours possible
Exemple :
i = (int) box;
Remarque : Le compilateur C# assure des oprations de boxing et de unboxing implicites entre les types "valeur" intgrs (natifs) et les classes qui leur correspondent en .NET. Ainsi par exemple : Une mthode qui prend comme paramtre formel Int32 peut accepter un paramtre effectif de type int (boxing implicite). Une mthode qui prend un paramtre formel de type int peut accepter un paramtre effectif de type Int32 (unboxing implicite).
21
Karim Kalti
Comparaison de chanes L'oprateur == effectue une comparaison des contenus des chanes et non une comparaison de rfrences
Exemple :
string s1="Bonjour", s2="Hello"; if(s1==s2)... if(s1==bonjour)
Extraction d'un caractre L'oprateur [] permet d'extraire un caractre de la chane mais il n'agit qu'en lecture : Exemple :
string s= "bonjour"; char c=S[0]; // C contient 'B' s[0] = 'X'; // erreur de syntaxe
Concatnation de chanes Les oprateurs + et += permettent de faire des concatnations de chanes Exemple :
string s, s1 = "Bon", s2 ="jour"; s = s1+s2; s+=" Monsieur"; // Bonjour monsieur
22
Karim Kalti
int IndexOf(char c, int pos) int IndexOf(string s) int IndexOf(string s,int Pos) String Insert(int pos, string s) String ToUpper() String ToLower()
Signification Renvoie la position du caractre c dans la chane qui porte l'opration.( 0 pour la premire position et 1si c n'a pas t trouv) Mme chose que la version prcdente sauf que la recherche commence partir de la position pos. Recherche la position de la chane s. Recherche la chane s partir de la position pos. Insre la chane s dans la chane appelante et ce partir de la position pos. Convertit la chane en majuscule. Convertit la chane en minuscule.
Classe Array
Cette classe reprsente les tableaux en .NET. Tout tableau cr avec la syntaxe du C# se comporte comme un objet de type Array. Quelques Proprits Length : Nombre total d'lments, toutes dimensions confondues. Rank : Nombre de dimensions. Exemple :
int[] t1 = {1,2,3}; // Length = 3 rank = 1 int [ , ] t2 = {{1,2,3},{10,20,30}}; // Length = 6 rank = 2 int [][] t3 = new int[2][]; // Length = 2 Rank = 1 t3[0]= new int[]{1,2,3}; t3[1] = new int[]{10,20,30,40}; // t3.Length vaut 2, t3[0].Length vaut 3, t3[1].Length vaut 4
Signification Copie tout le tableau sur lequel porte l'opration dans le tableau pass en argument partir de la position pos. (Il existe d'autres surdfinitions de cette mthode). Mthode statique qui renvoie l'indice de la premire occurrence du second argument dans le tableau t ou 1 si o n'a pas t trouv. (Il existe d'autres surdfinitions de cette mthode).
string[] ts={"Ali", "salah", "salem", "mehdi"}; n = Array.IndexOf("Salah"); // n=1
Mthode statique qui trie un tableau une dimension Mthode statique qui recherche un objet dans un tableau. Elle renvoie l'emplacement de l'objet dans le tableau ou une valeur ngative si l'objet n'a pas t trouv. Le tableau doit tre tri car c'est la technique de recherche dichotomique qui est utilise. Renvoie le nombre d'lments suivant une dimension spcifique.
int[ , ] M = new int[3,6]; for(int i = 0;i<M.GetLength(0);i++){ for(int j = 0;j<M.GetLength(0);j++){ M[i][j] = i+j; }}
23
Karim Kalti
La classe Math Elle renferme toutes les fonctions mathmatiques. Exemple : fonction de calcul de la valeur absolue
int i; i = Int32.Parse(Console.ReadLine()); Console.WriteLine("Valeur absolue de i :"+ Math.Abs(i));
Il existe galement d'autres classes qui peuvent s'avrer utiles comme : La classe ArrayList : pour la gestion des tableaux dynamiques. La classe DateTime : pour la gestion de la date et l'heure. Etc
24
Karim Kalti
Proprits et Indexeurs
Les proprits
Une proprit est un champ public particulier, qui est gnralement associ un champ priv de la classe et qui permet de dfinir les droits d'accs en lecture et en criture ce champ priv. La dfinition de ces droits d'accs est faite travers deux mthodes spciales associes la proprit. Ces mthodes, appeles accesseurs, sont les mthodes get et set. Accesseur get Cette mthode rend la proprit accessible en lecture. Elle retourne la valeur du champ auquel est associe la proprit. La mthode get est automatiquement excute lors de la lecture de la proprit. Accesseur set Cette mthode rend la proprit accessible en criture. Elle affecte une valeur au champ associ la proprit. La mthode set est automatiquement excute lors de l'affectation d'une valeur la proprit.
get
Syntaxe :
public type proprit{ get{return champ ;} set{champ = value;} }
Remarque : Si laccesseur get est absent alors la proprit est en criture seule. Si laccesseur set est absent alors la proprit est en lecture seule. Exemple :
..... private int champ; public int prop1{ get {return champ*10;} set {champ = value + 5 ;} } ..... prop1 = 14 ; // Champ contient alors 19 int X = prop1; // X vaut 190
Outre la protection des champs, les accesseurs servent galement automatiser les oprations usuelles appliques aux champs. L'exemple suivant illustre ceci.
25
Karim Kalti
Exemple :
using System ; namespace ProjProp { class clA { private double prixTTC ; private double Taxe = 1.12; public double prix { get {return Math.Round(PrixTTC);} set {PrixTTC = value*Taxe;} } } class Class { static void Main(){ clA Obj = new clA(); double val = 55; System.Console.WriteLine("Valeur entre:"+val); Obj.prix = val ; System.Console.WriteLine ("Valeur stocke:"+PrixTTC); val = Obj.prix ; System.Console.WriteLine ("valeur arrondie:"+val) ; System.Console.ReadLine ( ); } } }
Proprits de classes et proprits dobjets Comme c'est le cas pour les champs classiques, il est possible de dclarer des proprits de classe et des proprits d'instance. Une proprit de classe est dclare l'aide du mot-cl static. Une proprit statique ne peut tre associe qu' un champ statique. Exemple de proprit de classe:
using System ; namespace ProjProp { class Class { static private double PrixTTC ; static private double Taxe = 1.12 ; static public double prix { get {return Math.Round(PrixTTC);} set {PrixTTC = value * Taxe;} } static void Main(){ double val = 55 ; System.Console.WriteLine("Valeur entre:"+val ); prix = val ; System.Console.WriteLine ("Valeur stocke:"+PrixTTC); val = prix ; System.Console.WriteLine ("valeur arrondie:"+val) ; System.Console.ReadLine(); } } }
Masquage de proprits Il est possible de masquer une proprit par une autre la manire des mthodes et ce l'aide du mot rserv new. Exemple :
using System; class clA { private double PrixTTC ; private double Taxe = 1.12 ; public double prix { // proprit de la classe mre get { return Math.Round(PrixTTC);} set { PrixTTC = value * Taxe;} } }
26
Karim Kalti
class clB : clA { private double prixLocal ; public new double prix { // masquage de la proprit de la classe mre get {return Math.Round(prixLocal);} set { prixLocal = value * 1.05 ; } } } class Class { static void Main(){ clA Obj = new clA(); double val = 55 ; System.Console.WriteLine("Valeur entre obj1:"+val); Obj.prix = val ; val = Obj.prix ; System .Console.WriteLine ("valeur arrondie obj1:"+val); System .Console.WriteLine ("--------------------"); clB Obj2 = new clB ( ); val = 55 ; System .Console.WriteLine ("Valeur entre Obj2:"+val ); Obj2.prix = val ; val = Obj2.prix ; System .Console.WriteLine ("valeur arrondie Obj2:"+val ) ; } }
Remarque : Les proprits peuvent galement tre virtuelles et redfinies dans les classes drives.
Les indexeurs
Les indexeurs constituent un moyen permettant d'accder aux objets la manire des tableaux. Un indexeur est dclar avec le mot-cl this. Il possde deux mthodes get et set comme les proprits. Exemple 1 : Dfinition d'un indexeur
class clA { private int[] champ; public clA(){champ = new int [5]}; public int this [int index]{ get { return champ[ index ] ; } set { champ[ index ] = value ; } }
Remarque : Lindex utilis par l'indexeur peut tre de nimporte quel type. Plusieurs indexeurs peuvent tre dfinies pour une mme classe. Ils doivent se distinguer obligatoirement par leurs signatures. Exemple :
using System; class Pre { string[] Enfants; public void SesEnfants(string[] E) { Enfants = new string[E.Length]; for(int i=0;i<Enfants.Length;i++) Enfants[i]=E[i]; }
27
Karim Kalti
public string this[int n] { get{ return Enfants[n];} set{ Enfants[n] = value;} } public int this[string Nom] { get{ for(int i=0;i<Enfants.Length;i++) if(Enfants[i]==Nom) return i; return -1; } } } class Prog { public static void Main() { Pre Ammar = new Pre(); String[] Noms = {"Salah","Ali","Mehdi"} Ammar.SesEnfants(Noms); Console.WriteLine(Ammar[1]); Console.WriteLine(Ammar["Salah"]); Ammar[0]="Salem"; Console.WriteLine(Ammar[0]); } }
28
Karim Kalti
Dlgus et vnements
Rappel C/C++
En C/C++, le nom d'une fonction, utilis seul, dsigne ladresse en mmoire o sont stockes les instructions de cette fonction. De ce fait, il est possible de dclarer des pointeurs sur les fonctions et d'initialiser ces pointeurs. La dclaration d'un pointeur sur une fonction se fait comme suit : Type (*pf)(arg1, , argn) Exemple :
int (*pf)(int i double j)
pf est un pointeur qui peut pointer sur toute fonction qui prend comme paramtres un entier et un double et qui retourne un entier. Soit la fonction : int f (int K, double L) ; Si on initialise pf avec f : pf = f Alors lappel de f peut tre fait travers pf : int i = f(5,7.8) est quivalent int i = (*pf)(5,7.8)
La notion de dlgu
En C#, les pointeurs sur les fonctions sont implments l'aide des dlgus. Un dlgu est un objet particulier qui peut rfrencer (pointer vers) une ou plusieurs mthodes. Comme les pointeurs sur les fonctions, un dlgu doit tre dfini pour un prototype donn de mthodes. Il peut par la suite rfrencer nimporte quelle mthode ayant ce prototype. La mthode rfrence peut changer en cours de lexcution du programme. Lappel de la mthode peut se faire dans ce cas travers le dlgu. Dclaration dun type dlgu Pour pouvoir dclarer un dlgu, il faut dfinir auparavant le modle (prototype) des mthodes qui peuvent tre rfrences par ce dlgu. Ce modle de mthodes dfinit ce que l'on appelle un type dlgu. La dfinition d'un type dlgu se fait l'aide du mot-cl delegate comme suit : delegate TypeRetour TypeDlqu(type1 arg1,..., typeN argN) Instanciation dun objet de type dlgu Une fois le type dlgu dfini, il devient possible de crer des dlgus de ce type. Cette cration se fait comme suit : Typedlgu Deleg = new Typedlgu(NomMthode) Deleg est un dlgu qui peut rfrencer des mthodes ayant le prototype donn dans la dclaration de TypeDlgu. NomMthode dsigne ici le nom de la mthode qui sera rfrence par Deleg. Lappel de la mthode NomMthode peut se faire travers Deleg.
Exemple:
delegate string Dlgu(int x); class ClasseA { static string Fonc1(int x) { return (x*10).ToString(); }
29
Karim Kalti
static string Fonc2(int x) {return (x*100).ToString();} static void Main(){ string s = Fonc1(50); // appel de fonction classique System.Console.WriteLine("Fonc1(50) = " + s ); s = Fonc2(50); // appel de fonction classique System.Console.WriteLine("Fonc2(50) = " + s ); System.Console.WriteLine ("dlgu rfrence Fonc1 :"); Dlgu FoncDeleg = new Dlgu (Fonc1) ; s = FoncDeleg(50); // appel au dlgu qui appelle la fonction System.Console.WriteLine ("FoncDeleg(50) = " + s ); System.Console.WriteLine ("dlgu rfrence maintenant Fonc2 :"); FoncDeleg = new Dlgu ( Fonc2 ) ; // on change d'objet rfrenc (de fonction) s = FoncDeleg ( 50 ); // appel au dlgu qui appelle la fonction System.Console.WriteLine ("FoncDeleg(50) = "+s); System.Console.ReadLine ( ); } }
Remarque : Il est noter quil est tout fait possible de crer un dlgu faisant rfrence une mthode dinstance. Cette cration se fait comme suit : 1- Dclarer une classe contenant une mthode publique :
class clA { public int meth1(char x) { .... } }
Dlgu multicast
En C/C++, la fonction pointe par un pointeur peut tre variable et peut donc changer durant lexcution du programme. Toutefois, un instant donn, le pointeur ne peut pointer que sur une seule fonction. Par rapport ceci, en C#, un dlgu peut faire rfrence un instant donn plusieurs fonctions en mme temps. Ce type de dlgu est appel dlgu multicast. Les mthodes rfrences par un dlgu multicast doivent avoir le mme prototype. Elles peuvent tre des mthodes de classes ou des mthodes dinstances. Lajout dune rfrence un dlgu multicast se fait laide de loprateur dadition += comme suit : NomDlgu += new TypeDlgation(NomMthode); Exemple :
delegate int Dlgu(char x); class ClasseA { public int champ; public int meth100 ( char x ) { System.Console.WriteLine ("Excution de meth100('"+x+"')"); return x+100 ; } public int meth101 ( char x ) { System.Console.WriteLine ("Excution de meth101('"+x+"')"); return x+101 ; } public int meth102 ( char x ) { System.Console.WriteLine ("Excution de meth102('"+x+"')"); return x+102 ; } public static int meth103 ( char x ) { System.Console.WriteLine ("Excution de meth103('"+x+"')"); return x+103 ; }} class Prog { static void Main ( ) { ClasseA ObjA = new ClasseA( ); //-- instanciation du dlgu avec ajout de 4 mthodes : Dlgu FoncDeleg = new Dlgu( ObjA.meth100 ) ;
30
Karim Kalti
FoncDeleg += new Dlgu ( ObjA.meth101 ) ; FoncDeleg += new Dlgu ( ObjA.meth102 ) ; FoncDeleg += new Dlgu ( ClasseA.meth103 ) ; //--la mthode meth103 est en tte de liste : //--Appel du dlgu sur le paramtre effectif 'a' : ObjA.champ = FoncDeleg('a') ; //code ascii 'a' = 97 System.Console.WriteLine ( " valeur du champ : "+ObjA.champ) ; }}}
Suppression d'une rfrence une mthode dans un dlgu multicast : Il est possible de supprimer une rfrence une mthode laide de loprateur -= comme suit : NomDlgu -= new TypeDlgation(NomMthode); Exemple :
FoncDelg -= new dlgu (ClasseA.meth103) ;
Les vnements
Les vnements permettent de capturer une action dans un programme. Ils jouent un rle trs important dans les programmes tournant sous windows (utilisant les contrles graphiques de windows : bouttons, formulaires, menus). Les vnements dfinissent un style de programmation part entire appel programmation vnementielle. Lorsquun vnement a lieu, il doit tre intercept (par la machine virtuelle CLR dans les programmes manags et par Windows dans les programmes Win32). Le programme doit ragir galement cet vnement et entreprendre les actions ncessaires. Implmentation dun mcanisme de dtection et de gestion dvnements. Pour raliser une gestion des vnements en .Net, il faut procder comme suit : Dfinir le type des vnements dtecter. Dfinir un module de dtection (MD) de ce type d'vnements appel galement source dvnements. Dfinir un module de traitement des vnements (MT) appel galement gestionnaire dvnements. Lorsquun vnement est dtect par le MD ; ce dernier doit connatre le MT capable de traiter cet vnement. Pour cela le MT doit tre connu par le MD pour que ce dernier puisse linformer. On dit que le MT doit tre dans la liste de notification du MD. La liste de notification dun MD peut comporter un ou plusieurs MT. Un MT peut se retirer de la liste de notification dun MD sil ne veut plus traiter les vnements dtects par ce dernier. Le traitement dun vnement par le MT se fait en ralit travers une fonction FT de ce dernier ayant le mme prototype que lvnement. Le MD doit tre capable dappeler les FT de nimporte quel MT faisant partie de sa liste de notification. Pour cela il doit disposer dun dlgu qui peut faire rfrence ces FT. Dclaration du type de lvnement (dlgu) 1- Dfinition du type de dlgation public delegate TypeRetour TypeEvenement(Liste d'arguments); 2- Dclaration de lvnement laide du mot-cl event. public event TypeEvenement NomEvenement; Normalisation des vnements en .NET pour dclarer lvnement il est possible dutiliser un dlgu ayant nimporte quel prototype, suivant les besoins du programme bien sr. Toutefois le .Net recommande dutiliser lun des deux prototypes normaliss suivants : delegate void TypeDelegation(Object sender, EventArgs e) delegate void TypeDelegation(Object sender, MonEventArgs e)
31
Karim Kalti
o : sender dsigne lobjet source de lvnement. e dsigne un objet contenant les paramtres de lvnement. e peut ne pas contenir d'informations. Dans ce cas il est de type EventArgs. EventArgs est la classe de base des classes qui peuvent contenir les informations associes aux vnements. Elle comporte quelques fonctions utilitaires telles que le test dgalit entre objets, la conversion de donnes vers le type string, etc. e peut comporter des informations personnalises. Dans ce cas e doit tre un objet driv de la classe EventArgs (exemple MonEventArgs). Les champs ajouts lors de la drivation contiennent normalement les donnes personnalises de lvnement. Autres recommandations : Le nom du type de dlgation doit se terminer par EventHandler. Le nom de la mthode qui dclenche lvnement doit tre de la forme OnNomEvenement. Cette mthode est gnralement dclar comme protge. Le lancement de lvnement se fait travers une mthode publique qui appelle la mthode protge de dclenchement de lvnement. Etapes pour la mise en place dun vnement avec informations personnalises 1- Une classe d'informations personnalises sur l'vnement. 2- Une dclaration du type dlgation normalise (nom qui se termine par EventHandler). 3- Une dclaration d'une rfrence NomEvenement du type dlgation normalise spcifie event. 4- Une mthode protge OnNomEvenement qui dclenche l'vnement NomEvenement. 5- Une mthode publique qui lance l'vnement par appel de la mthode OnNomEvenement. 6- Un ou plusieurs gestionnaires de l'vnement NomEvenement. 7- Abonner ces gestionnaires au dlgu NomEvenement. 8- Consommer l'vnement NomEvenement. Droulement des tapes travers un exemple :
using System; //1) une classe d'informations sur l'vnement public class ExamenEventArgs { public string DateExamen; public ExamenEventArgs( string S){ DateExamen = S;} } // 2) une dclaration du type dlgation public delegate void EvenementExamen(Object sender, ExamenEventArgs e); public class MD { // 3) une dclaration d'une rfrence NomEvenement du type de dlgation public event EvenementExamen Examen; // 4) une mthode protge qui dclenche l'vnement NomEvenement protected void OnExamen (Object sender, ExamenEventArgs e) { if (Examen!=null) Examen(sender,e); } // 5) une mthode publique qui lance l'vnement par appel de la // mthode NomEvenement public void LancerEvenement() { ExamenEventArgs e = new ExamenEventArgs("15-01-05"); OnExamen(this, e); } } class MT { // 6) un ou plusieurs gestionnaires de l'vnement NomEvenement static void Message(Object sender, ExamenEventArgs e) { Console.WriteLine("Attention l'examen s'approche"); Console.WriteLine("la date de l'examen est: " + e.DateExamen); }
32
Karim Kalti
// 7) abonner ces gestionnaires au dlgu NomEvenement public MT(MD md) { md. Examen+= new EvenementExamen(Message); } } class Prog { static void Main() { MD md = new MD(); MT mt = new MT(md); // 8) consommer l'vnement md.LancerEvenement(); } }
33
Karim Kalti
public static void Main() { X x = new X(); // Inscription de la fonction de traitement x.MyEvent+= new TypeEvent(FT); // Invocation indirecte de l'vnement x.InvokeEvent(); } }
Pour pouvoir invoquer un vnement partir d'une classe drive, il suffit de dclarer une mthode protge dans la classe de base qui invoque en interne l'vnement. (il s'agit toujours d'une invocation indirecte) Mme si la mthode protge est dfinie comme virtuelle et qu'elle est redfinie dans la classe drive, alors la redfinition ne pourra pas invoquer directement l'vnement. Tout ce qu'elle peut faire c'est l'appel de sa version protge de la classe de base.
Exemple :
class Y:X { protected override void InvokeEvent() { // MyEvent(); ERROR base.InvokeEvent(); }
Le mot-cl event permet donc de crer un dlgu dont les droits d'invocation sont plus restreints que ceux d'un dlgu classique. En effet, par dfaut, le droit d'invocation d'un vnement est restreint l'intrieur de la classe dans laquelle est dclare cet vnement. Ensuite, c'est le propritaire de cette classe qui peut tendre ou non ce droit d'invocation aux utilisateurs de la classe en dfinissant ou non une mthode (publique ou protge) d'invocation indirecte. A la lumire de ce qui vient d'tre susmentionn la question suivante se pose : pourquoi dclare-t-on un vnement public s'il ne peut pas tre invoqu de l'extrieur ? La rponse cette question rside dans le fait qu'un vnement a besoin de rfrencer une (ou plusieurs) mthode(s) pour qu'il puisse tre trait. Cette opration se fait travers l'inscription de la (des) fonction(s) de traitement auprs de l'vnement. L'inscription se fait de l'extrieur de la classe qui contient l'vnement (par un objet externe) ce qui oblige par consquent l'vnement tre accessible de l'extrieur donc public. Diffrence au niveau de l'accs Accs un dlgu Un dlgu classique est accessible de plusieurs manires : Deleg = new TypeDelegation(NomMethode) pour un dlgu unicast ou pour inscrire une premire fonction auprs d'un dlgu multicast. Deleg+= new TypeDelegation(NomMethode) pour ajouter une inscription un dlgu multicast qui rfrence dj au moins une fonction. L'instruction Deleg = new TypeDelegation(NomMethode) applique un dlgu qui rfrence dj une (ou plusieurs) mthode(s) engendre la suppression de toutes ces mthodes de la liste de notification du dlgu. Le mme effet est obtenu avec l'instruction : Deleg = null; La suppression d'un gestionnaire de la liste de notification d'un dlgu multicast se fait l'aide de -=. Accs un vnement A la diffrence d'un dlgu, un vnement n'accepte que les accs l'aide des oprateurs += et -=. Cette restriction permet d'introduire un niveau de scurit supplmentaire. En effet, de par sa dfinition un vnement doit tre capable de dclencher une ou plusieurs actions (Exemple : un accident peut dclencher un appel au SAMU et un autre appel la police). Techniquement cela se traduit par le fait qu'un vnement doit tre capable d'accepter les inscriptions indpendantes de plusieurs gestionnaires d'vnements (fonctions de traitement). Toutefois, si par erreur une inscription se fait l'aide de l'oprateur = alors que d'autres gestionnaires sont dj inscrits alors ces derniers seront tout simplement limins de la liste de notification. Pour viter ce risque et pour donner plus de scurit et d'indpendance au processus d'inscription, le .NET n'autorise un gestionnaire s'inscrire auprs d'un vnement qu' l'aide de l'oprateur += (ceci est valable mme pour l'inscription du premier gestionnaire). De mme la dsinscription ne peut tre ralise qu'avec l'oprateur -= et elle touche un seul gestionnaire la fois. Ainsi, si un vnement est sollicit par plusieurs gestionnaires, alors chaque gestionnaire
34
Karim Kalti
ne pourra agir que sur sa propre fonction de traitement sans risquer de toucher les fonctions des autres gestionnaires. Remarque : Une telle restriction permet par exemple de garantir aux composants logiciels que leurs utilisateurs (gnralement les programmes qui intgrent ces composants) ne peuvent pas engendrer (par erreur ou par malveillance) en ajoutant un traitement personnalis un vnement la suppression d'un ventuel traitement prdfini, intgr par dfaut, et indispensable pour le bon fonctionnement de ces composants.
35
Karim Kalti
Les classes
Dclaration
Une classe dfinit un nouveau type de donnes. Une classe peut comporter : o des attributs, des proprits et des indexeurs. o des mthodes, des dlgus et des vnements. Une classe est dfinie avec le mot rserv class. Le point virgule aprs la dclaration dune classe est optionnel. Exemple :
class Pers { string Nom ; string Prenom; int Age; }
NomClasse RefObjet; // Dclaration d'une rfrence un objet RefObjet = new ConstructeurNomClasse(<arguments>); // instanciation
Les deux instructions prcdentes peuvent tre regroupes en une seule comme suit :
Exemple :
Pers p ; // p est une rfrence un objet de type Pers p = new Pers( ) ; // Instanciation // Les parenthses sont requises mme si le constructeur est absent ou nadmet pas // darguments.
Libration Elle se fait dune manire automatique par le GC. La libration se fait si : o On quitte le bloc o l'objet a t dclar. o On affecte l'objet la rfrence d'une nouvelle instance de la classe ou si on lui affecte la rfrence "null".
36
Karim Kalti
Les droits d'accs en C# doivent tre dfinis individuellement pour chaque membre de la classe. Si aucun droit d'accs n'est explicitement spcifi devant un membre, alors ce dernier sera considr par dfaut comme tant priv.
Le champ TotalPoints est explicitement initialis 100. Pour toute nouvelle instance de la classe Jeu, ce champ vaudra 100. Un champ non explicitement initialis prend la valeur 0 s'il est numrique, false s'il est boolen, espace s'il est caractre et chane vide s'il est de type chane. La valeur du champ peut tre modifie tout moment durant l'excution.
Les mthodes
Le corps d'une mthode doit se trouver dans la dfinition de la classe. (pas de possibilit de dfinition des mthodes l'extrieur de la classe comme en C++). Il n'y a pas de fichiers d'enttes (fichiers .h). L'emplacement de la dfinition d'une classe ou d'une mthode n'a pas d'importance par rapport au lieu de son appel. Exemple :
using System; class Pers { public string Nom; public int age; public void Affiche() {Console.WriteLine(Nom+"("+Age+")");} } class Prog { static void Main() { Pers p = new Pers(); P.Nom ="Ali"; P.Age=20; P.Affiche(); }}
La surcharge de mthodes
Plusieurs mthodes d'une classe peuvent porter le mme nom. Elles doivent cependant se distinguer par leurs signatures (nombre, ordre et types des paramtres). Ces mthodes sont dites surcharges. Deux mthodes surcharges ne peuvent pas se distinguer seulement par le type de leurs valeurs de retour.
37
Karim Kalti
Exemple :
class Pers { string Nom="Moi"; int Age = 20; public void Modifier(string N){Nom=N;} public void Modifier(int A){Age=A;} public void Modifier(string N, int A){Nom=N;Age=A;} } class Prog { static void Main() { Pers P = new Pers(); P.Modifier("Ali"); P.Modifier("Salah",25); } }
Les constructeurs
Les constructeurs possdent globalement les mmes caractristiques qu'en C++. Une classe peut comporter un ou plusieurs constructeurs. Dans le cas d'existence de plusieurs constructeurs ces derniers doivent respecter les rgles de surcharge de mthodes. Ils doivent porter le mme nom que celui de la classe. Ils peuvent admettre 0, un ou plusieurs paramtres. Ils ne renvoient rien. Leur dclaration explicite n'est pas obligatoire. En cas d'absence de dclaration explicite d'un constructeur, un constructeur par dfaut est automatiquement gnr pour la classe. En cas de prsence d'au moins un constructeur explicitement dfini, alors aucun constructeur par dfaut n'est gnr. Exemple 1 : Utilisation du constructeur par dfaut
Class NomClasse { } objet = new NomClasse(); // Appel du constructeur par dfaut
38
Karim Kalti
Liste d'initialiseurs Une liste d'initialiseurs permet l'appel d'un constructeur d'une classe par un autre constructeur de la mme classe. Une liste d'initialiseurs commence par le symbole : suivi de this et d'une liste d'arguments dfinie par la signature du constructeur appel. Exemple :
class Text { int a; int b; string str; public Text(): this(0, 0, null) {} public Text(int x, int y): this(x, y, null) {} public Text(int x, int y, string s) { a=x; b=y; str=s; } }
Destructeur
La notion de destructeur existe en C# bien qu'elle ne soit pas aussi utile qu'en C++. Un destructeur possde le mme nom que celui de la classe, prcd par ~. Un destructeur n'accepte aucun paramtre. Un destructeur n'accepte aucun modificateur d'accs (public private, ). Un destructeur en C# ne peut pas tre explicitement appel (pas d'instruction delete). Les destructeurs en C# ne sont pas dterministes comme en C++ : o En C++ le destructeur est automatiquement appel quand l'objet quitte sa zone de validit. o En C# le destructeur devient "appelable" pour un objet lorsque il n'existe plus de rfrence cet objet dans le programme. Toutefois on ne peut pas connatre exactement le moment de l'appel effectif du destructeur. Cet appel est en effet gr par le Garbage Collector. Il est effectu lorsqu'un besoin en mmoire se manifeste.
Exemple :
class Pers { string Nom; int Age; public Pers(string N) {// code du constructeur} ~Pers() {// code du destructeur} ... }
39
Karim Kalti
La mthode Dispose .NET met la disposition des programmeurs une mthode pouvant tre appele automatiquement lorsque la fin de la zone de validit d'un objet est atteinte. Cette mthode est appele Dispose. Il est possible de mettre dans Dispose le code destin tre plac dans le destructeur (libration des ressources). Pour qu'une classe garantisse au runtime que la mthode Dispose qu'elle implmente est celle devant tre appele la fin de la zone de validit de l'objet (mthode du .NET), cette classe doit implmenter l'interface IDisposable du .NET. Le prototype de Dispose est le suivant :
void Dispose() ;
Il est noter que la zone de validit dont il est question ici n'est pas automatiquement dtermine par le systme (en se basant sur les limites du bloc de dclaration comme c'est le cas en C++). Elle doit plutt tre dfinie explicitement par le programmeur l'aide de using comme suit :
Pers p = new Pers() ; using (p) // Definition de la zone de validit { ... ... } // fin de la zone de validit pour p
Il est galement possible de crer des zones de validit pour plusieurs objets :
Pers p = new Pers() ; Animal a = new animal(); using (p) using (a) { }
Les mthodes a.Dispose et p.Dispose seront automatiquement invoques (dans le sens inverse des using : a avant p) lorsque lexcution atteint laccolade fermante. Dispose peut tre : o explicitement appele : NomObjet.Dispose( ); o implicitement appele : en utilisant les zones de validit.
La mthode Finalize La mthode Finalize joue en .NET le mme rle jou par les destructeurs en C#. Cette mthode est automatiquement excute lorsqu'un objet est pris en charge par le GC. Finalize est une mthode de la classe Object, classe de base du .NET. Tout objet possde donc par dfaut une telle mthode. Comme pour les destructeurs, on met dans Finalize le code de libration des ressources. Finalize ne peut pas tre explicitement appele. Le moment d'appel de Finalize n'est pas dterministe. Cet appel tant dcid et fait par le GC lorsqu'un besoin en mmoire se manifeste. En .NET Finalize assure un mcanisme de destruction mme pour les langages qui ne supportent pas en natif un tel mcanisme (absence de la notion de destructeur au sens du C++ ou du C#).
40
Karim Kalti
Exemple :
Pers[] TP ; TP = new Pers[10] ; for(int i = 0; i <TP.Length ; i++) TP[i] = new Pers();
Membres statiques
Les champs et les mthodes dune classe peuvent tre qualifis de statiques. Les champs et les mthodes statiques existent sans ncessit dinstanciation de la classe. Le mot-cl static est utilis pour qualifier un champ ou une mthode de statique. Exemple :
class X { public public public public } int a ; // champ non statique static int b ; // champ statique void f(){} // mthode non statique static void g(){b++;} // mthode statique
Les champs statiques Un champ statique (appel galement champ de classe) : est accessible indpendamment de tout objet de la classe. Il existe mme si aucun objet de la classe na encore t cr. est partag par tous les objets de la classe. est accessible partir du nom de la classe : NomClasse.Champ; (Exemple : X.b) n'est pas accessible partir d'un objet : Obj.ChampStatique // erreur peut tre initialis et manipul par une mthode de la classe comme nimporte quel champ. Les mthodes statiques Une mthode statique (appele galement mthode de classe) : Peut tre appele en spcifiant directement le nom de la classe suivi du nom de la mthode. NomClasse.Methode(arguments) (Exemple : X.g() ;). Contrairement au C++, elle ne peut pas tre appele partir dun objet : Obj.MethodeStatique // erreur Ne peut accder quaux champs statiques de sa classe. Ne peut appeler que les mthodes statiques (de sa classe ou dune autre classe). Une mthode non statique (appele galement mthode d'instance) peut accder la fois aux champs statiques et non statiques. Elle peut appeler galement les mthodes statiques et non statiques.
Constructeur statique Un constructeur statique est un constructeur qui ne peut initialiser que les membres statiques d'une classe. Un constructeur statique ne possde jamais d'arguments. Un constructeur statique n'accepte pas les modificateurs d'accs (public, private, ).
41
Karim Kalti
Syntaxe : class X { static X() { } } Un constructeur statique ne peut pas tre appel explicitement. Un constructeur statique est appel implicitement suite l'instanciation d'un objet de la classe (il prcde l'appel du constructeur d'instance) ou lorsqu'un membre statique de la classe est appel. Exemple :
using System; class A { public static int i; public int j; static A() { Console.WriteLine("Constructeur statique"); i=5; } public A(int v) { Console.WriteLine("Constructeur d'instance"); j=v; } public A(int v1, int v2) { Console.WriteLine("Constructeur d'instance"); i=v1; j=v2; } public void Afficher() { Console.WriteLine("i vaut :"+i); Console.WriteLine("j vaut :"+j); } } class Prog { static void Main() { A a1 = new A(3); a1.Afficher(); // i = 5 et j=3 A a2 = new A(4,9); a2.Afficher(); // i = 4 et j=9 } }
42
Karim Kalti
Un objet de la classe B ne peut pas tre cr en dehors de la classe A. B est un objet local A. La partie publique de B peut tre accde par le membre public de A.
A a = new A(5) ; int n = a.getchprB(); // Ok car getchprB est publique. n= a.puB.chpu; // Ok car puB et chpu sont publiques
Hritage
Globalement similaire au C++. Pas dhritage multiple. Syntaxe : class ClasseDrive : ClasseDeBase { } Exemple : Hritage
class Pers { protected string Nom ; protected int Age; public Pers(string N, int A){ Nom = N; Age = A;} public void Afficher( ) { Console.WriteLine(Nom+ "(" + Age + ")");} } class Tunisien : Pers { string ville; public Tunisien(String N, int A, string V) : base (N,A) { Ville = V; } public new void Afficher() { Console.WriteLine(Nom+" Ag de " + Age + " ans (" + Ville+")"); } }
Appel du constructeur de la classe de base L'appel du constructeur de la classe de base se fait l'aide du mot-cl base. Lorsqu'il est utilis dans une classe drive, ce mot-cl permet de rfrencer la classe de base (classe mre). L'appel du constructeur de la classe de base peut tre omis. Dans ce cas c'est le constructeur par dfaut qui est appel. Si la classe de base possde un constructeur avec paramtres et si le constructeur par dfaut n'est pas explicitement dfini alors une erreur sera signale par le compilateur. Redfinition de mthode Il est possible de redfinir une mthode d'une classe de base dans une classe drive. Dans ce cas, la redfinition est gnralement prcde du mot-cl new. le new est optionnel, il sert gnralement amliorer la lisibilit du code en indiquant qu'il s'agit bien de la redfinition d'une mthode. Tout appel d'une mthode redfinie partir d'une instance de la classe drive va engendrer l'utilisation de la version dfinie dans la classe drive. Exemple 1 :
Tunisien T = new Tunisien ("Ali",20,"Monastir"); T.Afficher();
T est un objet de la classe Tunisien. L'instruction T.Afficher( ) va engendrer l'appel de la mthode Afficher de la classe Tunisien. Cette mthode cache la mthode Afficher de la classe Pers.
43
Karim Kalti
Pour P1 : c'est la mthode Afficher de la classe Pers qui est appele. Pour P2 : c'est la mthode Afficher de la classe Tunisien qui est appele. Afficher de Tunisien cache dans ce cas Afficher de Pers. Si Afficher de Tunisien n'tait pas dfinie, a serait Afficher de Pers qui aurait t appele. P3 = new Tunisien( ) est possible car tout objet Tunisien est de type Pers. P3.Afficher( ) excute la mthode Afficher de Pers car P3 a t dclare en tant que tel. Le compilateur se base dans ce cas sur la dfinition stricte. Les fonctions virtuelles Pour tenir compte du vritable type de P3 au moment de l'excution de P3.Afficher( ), il faut qualifier Afficher de virtual dans la classe de base et de override dans la classe drive.
class Pers { protected string Nom ; protected int Age; public Pers(string N, int A){ Nom = N; Age = A;} public virtual void Afficher( ) { Console.WriteLine(Nom+ "(" + Age + ")"); } class Tunisien : Pers { string Ville; public Tunisien(String N, int A, string V) : base (N,A) {Ville = V;} public override void Afficher() {Console.WriteLine(Nom+" Ag de " + Age + " ans (" + Ville+")");} } Pers p3; p3 = new Tunisien ("Salem",25,"Sousse"); p3.Afficher(); // Salem ag de 25 ans (Sousse)
Appel des mthodes caches par la redfinition Il est possible d'appeler une mthode d'une classe mre dans une classe fille mme si cette mthode a t redfinie dans la classe fille. Pour cela il suffit de faire prcder le nom de cette mthode par une rfrence la classe mre. Cette rfrence est obtenue l'aide du mot-cl base. Exemple : La mthode Afficher de Tunisien cache celle de Pers. Mais rien n'empche d'appeler cette dernire dans la classe Tunisien. Il suffit de faire prcder le nom de cette mthode par base.
Exemple : base.Afficher();
Redfinition de champs Il est possible de dfinir dans une classe drive un champ qui porte le mme nom qu'un champ de la classe de base. Pour distinguer entre les deux, il est possible d'crire : This.NomChamp : pour dsigner le nom du champ de la classe courante (classe drive). base.NomChamp : pour dsigner le nom du champ de la classe de base. Remarque : Il n'est pas possible de chaner l'utilisation de "base" pour accder aux membres d'une classe grand-mre.
Exemple : base.base.Affiche() // erreur
44
Karim Kalti
Identification du vritable objet instanci Il est possible de connatre le vritable type d'un objet instanci et ce l'aide du mot-cl "is". Exemple :
class Pers { public void Mariage(Pers Conjoint) { if(Conjoint is Tunisien) Console.WriteLine("Mariage avec compatriote"); else Console.WriteLine("Mariage avec tranger"); } } class Tunisien : Pers { string ville; public Tunisien(String N, int A, string V) : base (N,A) {Ville = V;} public override void Afficher() {Console.WriteLine(Nom+" Ag de " + Age + " ans (" + Ville+")");} } class Prog { static void Main() { Tunisien T = new Tunisien("Ammar",50,"Nabeul"); Pers P1 = new Tunisien ("Salma",45,"Kairouan"); Pers P2 = new Pers("Carla",45); T.Mariage(P1); // Mariage avec compatriote T.Mariage(P2); // Mariage avec tranger } }
Dans l'exemple 1, c'est une copie de rfrence qui a t effectue et non une copie d'objet. P1 et P2 font rfrence donc au mme objet. Pour effectuer une vritable copie d'objets il faut que la classe en question implmente la mthode Clone de l'interface IClonable. La mthode Clone possde le prototype suivant : public object Clone() Exemple 2 :
class Pers : IClonable { ... public object Clone() {return new Pers(Nom, Age);} }} ... p2=(Pers)p1.Clone();
Pers implmente l'interface IClonable. Elle propose en effet une dfinition de la mthode Clone dans laquelle est mis le code effectuant la copie explicite. La comparaison d'objets Une comparaison globale d'objets effectue en ralit une comparaison de rfrences et non une comparaison d'instances. Pour effectuer une vritable comparaison, il faut comparer les deux objets champ par champ. Exemple :
Pers P1,P2; ... P2==P1; est une
45
Karim Kalti
Les protections
Protection des classes Le seul qualificatif qui peut tre utilis avec les classes est public. Ainsi, si la classe est prcde de : public : alors il est possible de crer partout un objet de la classe. rien du tout : alors il est possible de crer un objet de la classe mais seulement dans le mme assemblage. Protection des membres Les membres d'une classe peuvent utiliser les qualificatifs suivants : public : signifie que toutes les mthodes (du mme assemblage ou non) peuvent accder ce champ ou appeler cette mthode. private : signifie que seules les mthodes de la classe ont accs un tel champ ou une telle mthode. Le fait domettre le qualificatif revient spcifier private. protected : signifie que seules les mthodes de la classe et des classes drives (du mme assemblage ou non) ont accs un tel champ ou une telle mthode. internal : signifie que seules les mthodes du mme assemblage ont accs un tel champ ou peuvent appeler une telle mthode. Interdiction de drivation Il est possible d'interdire toute drivation partir d'une classe et ce l'aide du qualificatif sealed. Exemple :
sealed class Tunisien : Pers { ... }
46
Karim Kalti
La classe Forme possde une mthode de calcul de la surface, mais cette mthode ne peut tre implmente que dans les classes drives (car il faut connatre la nature de la forme pour savoir comment calculer la surface).
Les interfaces
Dfinition Une interface est une classe qui ne comporte que des mthodes sans implmentation. On trouve seulement les prototypes de ces fonctions (il faut mettre les noms des paramtres formels). Les membres dune interface ne peuvent tre que des mthodes, des indexeurs, des proprits ou des vnements. Une interface ne peut pas comporter des champs. Une interface ne comporte pas des qualificatifs de protection (public, private,.). Le nom dune interface commence par I. Une interface est dfinie avec le mot-cl interface comme suit : interface NomInterface { Methode1(<Liste d'arguments>); ......... Methode2(<Liste d'arguments>); } Utilit des interfaces Une interface dfinie une sorte de cahier de charge concernant un certain comportement (ensemble d'oprations). Chaque classe qui implmente une interface garantit ses utilisateurs qu'elle est capable d'assurer les oprations dfinies par l'interface. Interface et drivation Il est possible de driver des classes partir dune interface. Si la classe drive propose des dfinitions aux mthodes de l'interface alors le processus de drivation s'appelle implmentation. L'implmentation d'une interface par une classe drive peut tre complte ou partielle. Une classe drive d'une interface n'est instanciable que si elle propose une implmentation complte de l'interface. Les mthodes implmentes dans les classes drives acceptent les qualificatifs de protection. Une interface peut driver dune autre interface (drivation sans aucune implmentation). Exemple : implmentation d'une interface par une classe
interface IB { void f1(int a); void f2(); } class X : IB { ... void f1(int a){...} void f2(){...} }
Implmentation de plusieurs interfaces Une classe ne peut driver que d'une seule autre classe. Elle peut par contre implmenter plusieurs interfaces en mme temps. Exemple : Soient IB et IC deux interfaces
class X : IB, IC { ... // champs et mthodes de X void f1(int a){...} // corps de mthodes de IB void f2(){...} // corps de mthodes de IB void g1(){...} // corps de mthodes de IC. }
47
Karim Kalti
Une classe drive peut avoir comme classes de base une classe et des interfaces. Dans ce cas, dans la dfinition de la classe drive, la classe de base doit tre liste en premier lieu. Exemple :
class ClassA: BaseClass, Iface1, Iface2 { // les membres de la classe }
Ambigut dimplmentation de plusieurs interfaces Deux interfaces peuvent comporter des mthodes portant le mme nom. Une classe qui implmente ces deux interfaces en mme temps doit alors rsoudre le problme dambigut dappel de telles mthodes. Exemple :
interface IB { void f(); void g(); } interface IC { double f(int a); void h(); }
Soit A une classe qui implmente IB et IC. Limplmentation de la mthode f doit alors tre associe chaque fois une rfrence de linterface laquelle elle se rapporte.
class A : IB, IC { void IB.f(){...} double IC.f(int a){...} }
48
Karim Kalti
Les exceptions
Les exceptions sont des erreurs qui ont lieu au moment de l'excution des programmes (pas au moment de la compilation) et qui ont pour cause une situation inattendue (exemple : tentative de lecture d'un fichier qui n'existe plus ou qui est dplac). Ancienne technique de gestion des erreurs d'excution Avec les langages qui ne supportent pas la gestion des exceptions (exemple C), le traitement des erreurs se fait gnralement en faisant des tests sur les valeurs de retour des fonctions. Ces dernires retournent le plus souvent des codes indiquant le type de l'erreur. Ces codes ne comportent pas des informations supplmentaires sur les causes et les paramtres des erreurs. En plus cette technique devient fastidieuse dans le cas d'appels imbriqus de fonctions (le gestion des erreurs complique le code surtout au niveau des fonctions internes). Avantage de la gestion d'exceptions Les mcanismes de gestion des exceptions permettent d'viter ces problmes : Il devient ainsi possible de grer un seul niveau les exceptions, mme celles engendres par des fonctions internes (Possibilit de centralisation de la gestion en des points prcis). Il est galement possible d'avoir plus d'informations sur les causes des erreurs. Les erreurs ne sont plus dcrites par des codes mais par des objets qui drivent tous d'une classe de base appele Exception et qui sont spcifiques chacun un type d'erreur bien prcis. Chaque objet comporte des informations qui dcrivent l'erreur. Familles d'exceptions Il existe deux grandes familles d'exceptions : Les exceptions gnres par le systme (runtime exception) comme les divisions par zro, l'accs un tableau en dehors de ses bornes, l'accs un fichier absent Les exceptions gnres par les applications. Ces exceptions sont gnralement de type smantique et dpendent du contexte de l'application. Comme exemple de ces exceptions, il est possible de citer la saisie d'une valeur trop leve pour l'age (250). C'est au programmeur de dfinir dans ce cas ce type d'exceptions. Gestion des exceptions La programmation oriente objet offre une solution structure de gestion d'erreurs sous la forme de bloc try et catch. L'ide est de sparer physiquement les instructions essentielles du programme qui grent son droulement normal des instructions de gestion d'erreurs. Le bloc try contient les instructions qui sont susceptibles d'engendrer une erreur. Le bloc catch contient le code de gestion d'erreurs. Syntaxe : try { // Bloc d'instructions du programme } catch(ClasseException e) { // Bloc de gestion des erreurs } Les accolades dans les blocs de try et de catch sont obligatoires mme si ces derniers comportent une seule instruction. Le type de ClasseException doit tre la classe System.Exception ou une classe qui drive de cette dernire. La porte de l'identificateur e est limite au bloc catch. Il est gnralement utilis pour rcuprer les informations sur l'erreur partir des attributs de ClasseException. S'il n'est pas fait usage de e dans le bloc catch alors cet identificateur peut tre omis. catch(ClasseException) { // Bloc de gestion des erreurs }
49
Karim Kalti
Droulement de l'excution Le programme entre dans le bloc de try comme si cette dernire instruction n'existait pas. Il commence alors l'excution squentielle des instructions de ce bloc. Ds qu'une erreur est dtecte par le systme ou par une mthode (qui lve une exception) un objet de la classe ClasseException est cr et le programme quitte le bloc try et rentre tout aussi automatiquement dans le bloc catch. Exemple :
using System; class Prog { static void Main() { int a = 5,b = 0,c; try { Console.WriteLine("Avant division"); c=a/b; Console.WriteLine("Aprs division c vaut "+c); } catch(Exception) {Console.WriteLine("Erreur sur opration arithmtique");} } }
Blocs catch multiples Le bloc de try peut comporter plusieurs instructions. Chaque instruction peut lever une ou plusieurs exceptions. Il est possible d'associer un tel bloc plusieurs blocs catch qui interceptent chacun un type d'exception particulier. En cas d'erreur le contrle passe au premier bloc catch. Si cette erreur correspond l'argument de ce premier bloc catch alors l'erreur est traite par ce bloc. Dans le cas contraire le catch suivant est inspect et ainsi de suite. Ds qu'une erreur est traite par un catch les catchs suivants ne sont plus envisags. Exemple :
using System; class Prog { static void Main() { int a = 5,b = 0,c; int[] T = new int[3]; try { Console.WriteLine("Donner un nombre"); c= Int32.Parse(Console.ReadLine()); Console.WriteLine("Avant division et accs au tableau"); T[c]=a/b; Console.WriteLine("Aprs division T["+c+"] vaut "+T[c]); } catch(ArithmeticException) {Console.WriteLine("Erreur sur opration arithmtique");} catch(IndexOutOfRangeException) {Console.WriteLine("Accs au tableau en dehors de ses bornes");} catch(Exception) {Console.WriteLine("Erreur");} Console.WriteLine("Aprs le traitement des erreurs"); } }
Commentaires Trois blocs catch sont associs au try. Le premier bloc gre les erreurs arithmtiques. La classe ArithmeticException est la classe de base de ce type d'erreurs. Voici la liste des classes exceptions qui en drivent :
System.ArithmeticException System.DivideByZeroException (Division par zero) System.NotFiniteNumberException (Valeur relle infinie ou valeur non numrique pour un rel) System.OverflowException (Dpassement de capacit)
Le deuxime bloc gre les erreurs d'accs un tableau en dehors de ses bornes.
50
Karim Kalti
Le troisime bloc gre les autres exceptions pouvant ventuellement avoir lieu. En effet Exception est la classe de base de toutes les exceptions. Donc toute exception ayant chapp aux deux premiers blocs sera obligatoirement intercepte par ce troisime bloc. Remarque : L'ordre des catchs est important surtout si leurs arguments sont des objets qui drivent les uns des autres. Par exemple si les blocs catchs de l'exemple prcdents taient organiss comme ceci :
catch(Exception) {Console.WriteLine("Erreur");} catch(ArithmeticException) // Bloc jamais excut {Console.WriteLine("Erreur sur opration arithmtique");} catch(IndexOutOfRangeException) // Bloc jamais excut {Console.WriteLine("Accs au tableau en dehors de ses bornes");}
Alors les deux derniers blocs ne pourraient jamais tre excuts car toute erreur est de type Exception (toutes les exceptions de type systme ou application drivent de System.Exception). Toute erreur serait de ce fait toujours traite par le premier bloc. Le bloc finally En plus des bloc try et catch, il est possible d'utiliser un troisime bloc optionnel dfini par finally. Les instructions de ce bloc sont toujours excutes quel que soit le droulement de l'excution dans le bloc try (erreur ou pas d'erreur). Le bloc finally est gnralement utilis pour assurer la libration des ressources (fermeture de fichiers, ) et ce en cas de leve d'une exception. Remarque : Un seul bloc finally peut tre associ un bloc try. Les accolades sont obligatoires mme si le bloc comporte une seule instruction. Mcanisme complet de gestion d'exceptions La syntaxe complte d'un mcanisme de gestion d'exception est : try { // Bloc d'instructions du programme } catch(ClasseException e) { // Bloc de gestion de l'erreur } finally { // Bloc toujours excut }
Exemple :
using System; class Prog { static void Main() { try { Console.WriteLine("Dbut du try du Main"); f(); Console.WriteLine("Fin du try du Main"); } catch(Exception) { Console.WriteLine("Erreur"); } }
51
Karim Kalti
static void f() { int a = 5,b,c; int[] T = new int[3]; ... // code de saisie de b et c try {Console.WriteLine("Dbut du try de f"); T[b] = a/c; Console.WriteLine("Fin du try de f"); } finally {Console.WriteLine("finally de f);} } }
Remarque : Propagation du mcanisme d'interception L'exemple prcdent montre qu'il est possible de ne pas intercepter une erreur la source (absence de catch dans le try de f). En effet suite la gnration d'une exception dans un bloc try, le runtime commence chercher un bloc catch capable de la traiter (en se basant sur le type de l'exception). S'il ne trouve pas un tel bloc dans la fonction appele, la recherche se propage vers la fonction appelante. Ce processus de propagation continu : Jusqu' ce que un catch appropri soit trouv, auquel cas le runtime considre que l'exception t intercepte et il reprend l'excution du programme partir du corps du bloc catch. Jusqu' ce que la fonction Main soit atteinte sans trouver un catch appropri. Dans ce cas le runtime met fin l'excution du programme. Dfinition d'exceptions personnalises En plus des exceptions "systme" qui sont prdfinies, il est possible au programmeur de dfinir ses propres exceptions. Ces dernires sont gnralement d'ordre smantique et dpendent de ce fait du contexte de l'application dveloppe. C'est pourquoi elles sont dites exceptions de type "application". La dfinition d'une exception personnalise passe par la dfinition d'une classe qui drive obligatoirement de la classe Exception. Il suffit gnralement de faire une simple drivation sans ajouter de membres supplmentaires. Il est galement possible d'inclure des attributs supplmentaires qui donneraient des informations utiles quant l'erreur. Leve d'exceptions Contrairement aux exceptions prdfinies o c'est le runtime qui lve automatiquement l'exception, pour les exceptions personnalises cette tche est la charge du programmeur. Elle est assure par l'instruction throw qui prend en argument un objet de la classe reprsentant l'exception. Exemple 1 :
if(minute<1 || minute >=60) { string Erreur = minute + "n'est pas une minute valide"; throw new InvalidTimeException(Erreur); // Partie jamais atteinte }
Exemple 2 :
using System; class MyException : Exception { public MyException(string msg) : base(msg) {} }
52
Karim Kalti
class Prog { static void f(int i) { if(i>10) throw new MyException(i+" est une valeur trop grande"); Console.WriteLine("Fin de la mthode f"); } static void Main() { int i=20; try { f(i); } catch(MyException e) { Console.WriteLine(e.Message); } } }
Principaux membres de la classe System.Exceptions Constructeurs Exception() Constructeur par dfaut Exception(string msg) Constructeur qui initialise l'attribut Message de la classe Exception. Proprits Nom Type Signification HelpLink string Nom de la page Web d'aide associe l'exception. Message string Message d'explication Source string Nom de l'objet ou de l'application ayant gnr l'erreur.
Classes d'exceptions usuelles en C# (ref MSDN) Classe de base pour les exceptions qui se produisent pendant des oprations arithmtiques, telles que
System.DivideByZeroException et System.OverflowException. System.ArrayTypeMismatchException
System.ArithmeticException
System.DivideByZeroException
System.IndexOutOfRangeException
System.InvalidCastException
System.NullReferenceException System.OutOfMemoryException
System.StackOverflowException
System.TypeInitializationException
Leve lorsqu'un stockage dans un tableau choue car le type rel de l'lment stock est incompatible avec le type rel du tableau. Leve l'occasion d'une tentative de division d'une valeur intgrale par zro. Leve lors d'une tentative d'indexation d'un tableau via un index qui est infrieur zro ou en dehors des limites du tableau. Leve lorsqu'une conversion explicite d'une interface ou d'un type de base vers des types drivs choue au moment de l'excution. Leve lorsqu'une rfrence null est utilise d'une manire qui rend obligatoire l'objet rfrenc. Leve par l'chec d'une tentative d'allocation de mmoire (via new). Leve lorsque la pile d'excution est puise par un trop grand nombre d'appels de mthode en attente ; c'est gnralement le signe d'une rcurrence trs profonde ou non lie. Leve lorsqu'un constructeur statique lve une exception, alors qu'il n'existe aucune clause catch pouvant l'intercepter.
53
Karim Kalti
Les IHM en C#
Introduction
Les Interfaces Homme-Machine (IHM) permettent de dvelopper des programmes informatiques dans lesquelles l'interaction entre l'utilisateur et le systme se fait dans un cadre convivial bas essentiellement sur des composants visuels. Le systme d'exploitation Windows donne une bonne illustration de ces interfaces et de leurs composants (Exemples : Fentres, Boites de dialogue, menus, boutons, boutons radio, cases cocher, etc.). En utilisant le .NetFrameWork, il est possible de dvelopper des applications disposant de telles interfaces.
La classe Form
Cette classe reprsente une fentre. Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.ScrollableControl System.Windows.Forms.ContainerControl System.Windows.Forms.Form
54
Karim Kalti
Type
bool
Description
Si vrai, la fentre pourra jouer le rle de destination dans une opration Drag&Drop. Si la valeur est true alors des barres de dfilement (scrollbar) sont automatiquement affiches lorsque la fentre devient trop rduite pour que tous les composants soient visibles. Si la valeur est false alors les barres de dfilement ne sont jamais affiches. Couleur d'arrire plan de la fentre. Image de fond de la fentre. Il est possible de spcifier une image au format bmp, gif, jpg ou ico. Cette image sera greffe dans l'excutable du programme. L'image ainsi spcifie est rpte autant de fois que ncessaire pour remplir toute la fentre. Forme que prend le curseur de la souris lorsqu'il survole la fentre. Couleur d'affichage du texte. Position du coin suprieur gauche de la fentre. Nom du menu associ la fentre Taille de la fentre. Size reprsente deux champs: Width et Height. Ces champs sont exprims en nombre de pixels. Reprsente le texte qui sera affich dans la barre de titre de la fentre. Nom interne de la fentre.
AutoScroll BackColor BackGroundImage Cursor ForeColor Location Menu Size Text Name
enum Cursors enum Color Objet Point Objet MainMenu Objet Size String String
Description
Description
Se produit lorsque la valeur de la proprit BackColor change. Se produit suite un clic sur le contrle (la fentre dans ce cas). Se produit lorsque le formulaire est ferm. Se produit pendant la fermeture du formulaire. Se produit lorsque le contrle reoit le focus. Se produit lorsque le contrle perd le focus. Se produit lorsqu'une touche est enfonce alors que le contrle a le focus. Se produit lorsqu'une touche est enfonce alors que le contrle a le focus. Se produit lorsqu'une touche est relche alors que le contrle a le focus. Se produit avant le premier affichage d'un formulaire.
Programme 1 using System; using System.Windows.Forms; namespace ApplicationTest { public class Exemple { static void Main( ) { Form fiche = new Form( ); fiche.Text="Exemple de Form"; fiche.BackColor=System.Drawing.Color.RosyBrown; fiche.Show( ); } } }
55
Karim Kalti
Explication des tapes de l'excution : Ligne d'instruction du programme { Form MaFentre = new Form( ); MaFentre.Show(); } Que fait le CLR Initialisation de l'excution de la mthode main Instanciation d'une fentre nomme MaFentre Affichage de MaFentre. Terminaison du processus.
La mthode Show de la classe Form affiche la fentre. Cet affichage va persister durant l'excution du Main. Ds que l'accolade fermante du Main est atteinte, le programme se termine et la fentre disparat en mme temps. La fugacit de l'affichage de l'exemple prcdent est due en fait l'absence d'instructions aprs la mthode Show. Pour remdier cela, il est possible d'ajouter une instruction qui bloque l'excution (Exemple : Console.Read();)
static void Main() { char a; Form MaFentre = new Form(); MaFentre.Show(); a=Console.Read(); }
Le blocage de l'excution avec la mthode Read, mme s'il rsout le problme de la fugacit de l'affichage reste inappropri pour le dveloppement d'application avec IHM. En effet, dans ce cas, et tout juste aprs l'instruction MaFentre.Show(), le programme passe directement l'instruction a=Console.Read()et attend la saisie d'un caractre. Toute autre action peut bloquer son excution et il devient dans ce cas difficile d'interagir avec la Fentre. Pour viter ce problme, il vaut mieux utiliser une boucle l'intrieur du Main dont le rle sera d'intercepter les vnements engendrs par le systme ou par l'interaction de l'utilisateur avec l'application. Cette boucle permettra entre autres d'viter d'atteindre la fin de l'application tant qu'un message d'arrt n'a pas t intercept. Elle assurera par la mme occasion une persistance de l'affichage des interfaces graphiques. Le .NET framework implmente une telle boucle et ce dans la classe Application. Le lancement de cette boucle se fait l'aide de la mthode Run. Exemple :
static void Main() { Form MaFentre = new Form(); MaFentre.Show(); Application.Run(); }
La mthode Run excute une boucle de messages d'application sur le thread en cours (processus associ l'application en cours d'excution). La structure de la boucle peut tre vue comme suit : tantque non ArrtSysteme faire si vnement alors Construire Message ; si Message ArrtSysteme alors Reconnatre le composant auquel est destin ce Message; Distribuer ce Message fsi fsi ftant
Autres surcharges de Run La mthode Run possde deux autres surcharges. La surcharge la plus utilise est celle qui prend en argument un objet de la classe Form et qui l'affiche. Cet objet reprsente gnralement la fentre principale de l'application. Prototype : public static void Run(Form);
56
Karim Kalti
Deuxime programme :
Programme 2 using System; using System.Windows.Forms; namespace Application { class PremierWinProg { static void Main() { Form MaFentre = new Form(); Application.Run(MaFentre); } } }
Remarques : Une seule boucle de messages est gnralement associe une application. Elle est lance avec la mthode Run. La surcharge la plus utilise de Run est celle qui prend en argument la fentre principale de l'application. Si l'application contient d'autres fentres, alors leur affichage sera fait travers leurs propres mthodes Show et non travers Application.Run comme c'est le cas pour la fentre principale.
Utilisation d'un RAD pour la gnration du code : Les environnements de dveloppement en C#.NET permettent de dvelopper de grandes parties des applications l'aide des assistants visuels. Ils gnrent galement d'une manire automatique le code correspondant aux parties ainsi dveloppes. Le programme suivant reprsente le code gnr pour un projet minimal affichant seulement un formulaire vide.
Programme 3 using System; using System.Windows.Forms; namespace DefaultNamespace { public class MainForm : System.Windows.Forms.Form { public MainForm() { InitializeComponent(); } public static void Main() {Application.Run(new MainForm());} private void InitializeComponent() {// Form1 this.ClientSize= new System.Drawing.Size(292, 266); this.Text = "MainForm"; this.Name = "MainForm"; } } }
57
Karim Kalti
Commentaires : La mthode InitialiazeComponent contient tout le code ncessaire linitialisation du formulaire et ventuellement ses composants. Cette mthode est gnre par le RAD. Elle est par la suite appele dans le constructeur de la fentre de base de lapplication. Il est possible dajouter dautres instructions dinitialisation dans la mthode InitailizeComponent ou directement dans le constructeur de la fentre.
La classe Button
Cette classe reprsente les boutons de commande. Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.ButtonBase System.Windows.Forms.Button
Type
enum Color enum Cursors bool Font enum FlatStyle enum Color Image Point String int bool Size String bool
Description
Couleur d'arrire plan du bouton. Forme que prend le curseur de la souris lorsqu'il survole le bouton. Obtient ou dfinit une valeur indiquant si un contrle peut rpondre une interaction utilisateur. Obtient ou dfinit la police du texte affich par le contrle. Obtient ou dfinit le style deux dimensions (flat) du contrle bouton. Couleur d'affichage du texte. Image d'avant plan. Position du coin suprieur gauche du bouton. Nom interne du bouton. Obtient ou dfinit l'ordre de tabulation du contrle dans son conteneur. Obtient ou dfinit une valeur indiquant si l'utilisateur peut octroyer le focus ce contrle l'aide de la touche TAB. Taille du bouton. Size reprsente deux champs: Width et Height. Ces champs sont exprims en nombre de pixels. Reprsente le texte qui sera affich sur le bouton. Obtient ou dfinit une valeur indiquant si le contrle est affich.
Description
Masque le bouton l'utilisateur. Dimensionne le contrle et ses contrles enfants. Surcharge. Active un contrle. Affiche le bouton l'utilisateur.
58
Karim Kalti
Description
Se produit lorsque la valeur de la proprit BackColor change. Se produit suite un clic sur le contrle. Se produit lorsque le contrle reoit le focus. Se produit lorsque le contrle perd le focus. Se produit lorsqu'une touche est enfonce alors que le contrle a le focus. Se produit lorsqu'une touche est enfonce alors que le contrle a le focus. Se produit lorsqu'une touche est relche alors que le contrle a le focus.
59
Karim Kalti
La classe Label
Cette classe reprsente une zone d'affichage de texte. Les contrles Label sont gnralement utiliss pour fournir un texte descriptif un contrle. Par exemple, il est possible d'utiliser Label pour ajouter un texte descriptif un contrle TextBox afin d'informer l'utilisateur du type des donnes attendues dans le contrle. Le contrle Label peut galement tre utilis pour ajouter un texte descriptif un Form afin de fournir des informations utiles l'utilisateur. Par exemple, il est possible d'ajouter un Label au dbut d'un Form qui fournit des instructions l'utilisateur sur la faon de faire entrer des donns dans les contrles du formulaire. Le contrle Label peut galement tre utilis pour afficher des informations sur l'tat d'une application au moment de l'excution. Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.Label
Type
enum Color enum BorderStyle enum Cursors bool Font enum FlatStyle enum Color Image Point string int bool Size string bool
Description
Couleur d'arrire plan du Label. Obtient ou dfinit le style de bordure du Label. Forme que prend le curseur de la souris lorsqu'il survole le Label. Obtient ou dfinit une valeur indiquant si le Label peut rpondre une interaction avec l'utilisateur. Obtient ou dfinit la police du texte affich par le Label. Obtient ou dfinit le style deux dimensions (flat) du contrle Label. Couleur d'affichage du texte. Image d'avant plan. Position du coin suprieur gauche du contrle Label Nom interne du Label. Obtient ou dfinit l'ordre de tabulation du contrle dans son conteneur. Obtient ou dfinit une valeur indiquant si l'utilisateur peut octroyer le focus ce contrle l'aide de la touche TAB. Taille du contrle Label. Size reprsente deux champs: Width et Height. Ces champs sont exprims en nombre de pixels. Reprsente le texte qui sera affich par le Label. Obtient ou dfinit une valeur indiquant si le contrle Label est affich.
Description
Masque le label l'utilisateur. Surcharge. Dimensionne le contrle Label et ses contrles enfants. Surcharge. Active un contrle Label. Affiche le contrle Label l'utilisateur.
Quelques vnements : Un label peut traiter la majorit des vnements associs la classe contrle. Toutefois, sur le plan pratique il est trs rare de grer ces vnements.
60
Karim Kalti
La classe TextBox
Le contrle TextBox reprsente les zones d'dition. Il permet d'entrer du texte dans une application. Il a t enrichi de fonctionnalits absentes du contrle zone de texte Windows standard, dont la modification multiligne et le masquage des caractres d'un mot de passe.
Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.TextBoxBase System.Windows.Forms.TextBox
Type
bool enum Color enum BorderStyle enum Cursors bool Objet Font enum Color Point string int bool char bool bool int bool Objet Size string bool
Description
Obtient ou dfinit une valeur indiquant si le fait d'appuyer sur la touche ENTRE dans un contrle TextBox multiligne entrane la cration d'une nouvelle ligne de texte dans le contrle ou bien l'activation du bouton par dfaut sur le formulaire. Couleur d'arrire plan du contrle TextBox. Obtient ou dfinit le type des bordures du contrle zone de texte. Forme que prend le curseur de la souris lorsqu'il survole le contrle TextBox. Obtient ou dfinit une valeur indiquant si un contrle peut rpondre une interaction utilisateur. Obtient ou dfinit la police du texte affich par le contrle TextBox. Couleur d'affichage du texte. Position du coin suprieur gauche du contrle TextBox. Nom interne du contrle TextBox. Obtient ou dfinit le nombre maximal de caractres que l'utilisateur peut taper dans le contrle zone de texte. Obtient ou dfinit une valeur indiquant si ce contrle est un contrle zone de texte multiligne. Obtient ou dfinit le caractre servant masquer les caractres d'un mot de passe dans un contrle TextBox monoligne. Obtient ou dfinit une valeur indiquant si le texte de la zone de texte est en lecture seule. Obtient ou dfinit une valeur indiquant si les lments du contrle sont aligns pour prendre en charge les paramtres rgionaux utilisant des polices de droite gauche (comme l'arabe). Obtient ou dfinit l'ordre de tabulation du contrle dans son conteneur. Obtient ou dfinit une valeur indiquant si l'utilisateur peut octroyer le focus ce contrle l'aide de la touche TAB. Taille du contrle TextBox. Size reprsente deux champs: Width et Height. Ces champs sont exprims en nombre de pixels. Reprsente le texte qui sera affich par le contrle TextBox. Obtient ou dfinit une valeur indiquant si le contrle est affich.
61
Karim Kalti
Description
Efface tout le texte du contrle zone de texte. Copie la slection active dans la zone de texte vers le Presse-papiers. Dplace la slection active entre la zone de texte et le Presse-papiers. Remplace la slection active de la zone de texte par le contenu du Presse-papiers. Annule la dernire modification apporte dans la zone de texte. Slectionne le texte qui commence depuis le caractre d'indice start et qui s'tend sur length caractre. Slectionne tout le texte du contrle. Masque la zone de texte l'utilisateur. Affiche le contrle TextBox l'utilisateur.
Exemple d'criture du contenu d'un Label Label Lb = new Label(); Lb.text = "Premier message"; Exemple de lecture du contenu dune zone ddition TextBox TB = new TextBox(); String s = TB.text ; Exemple montrant comment vider le contenu dune zone ddition TB.text = ""; ou TB.Clear() ;
Programme 5 : Exemple d'utilisation des contrles TextBox et Label using using using using using System; System.Drawing; System.Collections; System.ComponentModel; System.Windows.Forms;
public class Form1 : System.Windows.Forms.Form {private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox textBox1; public Form1() {InitializeComponent();} private void InitializeComponent() {this.label1 = new System.Windows.Forms.Label(); this.textBox1=new System.Windows.Forms.TextBox(); this.SuspendLayout(); // label1 this.label1.Location = new System.Drawing.Point(24, 24); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(72, 24); this.label1.TabIndex = 0; this.label1.Text = "Nom"; // textBox1 this.textBox1.Location =new System.Drawing.Point(88, 24); this.textBox1.Name = "textBox1"; this.textBox1.Size = new System.Drawing.Size(112, 20); this.textBox1.TabIndex = 1; this.textBox1.Text = ""; // Form1 this.ClientSize = new System.Drawing.Size(250, 100); this.Controls.Add(this.textBox1); this.Controls.Add(this.label1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } static void Main() {Application.Run(new Form1());} }
62
Karim Kalti
La classe CheckBox
Cette classe reprsente un contrle case cocher. Ce contrle permet de prsenter l'utilisateur la possibilit de slectionner ou non un choix. Une case cocher est gnralement accompagne d'un texte expliquant le choix faire. Un contrle case cocher peut avoir trois tats : non coch, coch, estomp. Un contrle case cocher peut tre utilis seul ou en groupe. Il est possible de regrouper thmatiquement des cases cocher dans un GroupBox. Ceci permet de faciliter leur manipulation (dplacement et positionnement) et permet l'utilisateur de faire des choix (non exclusifs) concernant le thme du groupe. Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.ButtonBase System.Windows.Forms.CheckBox
Constructeur : public
CheckBox();
Description
Indique l'apparence de la case cocher. Les valeurs possibles de l'numration Appearance sont : Button (la case prend la forme d'un petit bouton) et Normal (la case prend sa forme normale). Indique si la case change automatiquement d'tat suite un clic sur la case. Si AutoCheck vaut false, c'est alors au programmeur de grer l'tat de la case en traitant l'vnement Click. Indique l'tat (coch ou non) d'une case deux tats. Pour les contrles trois tats la proprit Checked retourne true pour les deux tats Checked et Intermediate. Etat d'une case trois tats. CheckState prend l'une des trois valeurs suivantes de l'numration CheckState (Checked, Unchecked, Indeterminate). Indeterminate correspond une case estompe (grise ). Indique si la case est deux ou trois tats : false : correspond une case deux tats. Elle peut tre coche (Checked) ou non coche (Unchecked). Cet tat est contrl par la proprit Checked. true : correspond une case trois tats. (coch, non coch, estomp). Cet tat est contrl par la proprit CheckState. Libell de la case. Le caractre & sert spcifier un acclrateur. ALT+Acclrateur permet de changer l'tat de la case. Obtient ou dfinit une valeur indiquant si le contrle peut rpondre une interaction utilisateur. Position du coin suprieur gauche du contrle case cocher. Nom interne du contrle case cocher. Obtient ou dfinit l'ordre de tabulation du contrle dans son conteneur. Obtient ou dfinit une valeur indiquant si l'utilisateur peut octroyer le focus ce contrle l'aide de la touche TAB. Obtient ou dfinit une valeur indiquant si le contrle est affich.
ThreeState
bool
63
Karim Kalti
Description
Description
Se produit suite un clic sur le contrle. Il est gnralement gr lorsque la proprit AutoChek est gale false. Se produit suite au changement d'tat d'une case deux tats. Se produit suite au changement d'tat d'une case trois tats.
Exemple 2 : Code de traitement d'un clic sur le contrle CheckBox "Service 1" Pour un contrle trois tats :
private void checkBox1_Click(object sender, System.EventArgs e) { switch(checkBox1.CheckState) { case CheckState.Checked: // Mettre ici le code pour l'tat checked. break; case CheckState.Unchecked: // Mettre ici le code pour l'tat unchecked. break; case CheckState.Indeterminate: // Mettre ici le code pour l'tat intermediate. break; } }
64
Karim Kalti
La classe RadioButton
La classe RadioButton reprsente un contrle bouton radio. Les contrles boutons radio reprsentent un ensemble de choix mutuellement exclusifs. Ils s'utilisent essentiellement en groupe et permettent alors l'utilisateur de slectionner une option parmi plusieurs. Le contrle bouton possde quelques exceptions prs les mmes caractristiques que le contrle case cocher, toutefois : o Dans un groupe de boutons radio, une et une seule option peut tre slectionne alors que dans un groupe de cases cocher, il est possible de slectionner autant d'options que voulues. o Un contrle bouton radio ne possde que deux tats possibles (Checked et Unchecked). Il n'a pas comme pour les cases cocher un tat estomp.
Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.ButtonBase System.Windows.Forms.RadioButton
RadioButton();
Type
Enum Appearance bool bool string bool Point string int bool bool
Description
Indique l'apparence de la case cocher. Les valeurs possibles de l'numration Appearance sont : Button (la case prend la forme d'un petit bouton) et Normal (la case prend sa forme normale). Indique si le bouton radio change automatiquement d'tat suite un clic. Si AutoCheck vaut false, c'est alors au programmeur de grer l'tat de la case en traitant l'vnement Click. Indique l'tat (coch ou non) du bouton. Libell du bouton radio. Le caractre & sert spcifier un acclrateur. ALT+Acclrateur permet de changer l'tat du bouton. Obtient ou dfinit une valeur indiquant si le contrle peut rpondre une interaction utilisateur. Position du coin suprieur gauche du contrle bouton radio. Nom interne du contrle bouton radio. Obtient ou dfinit l'ordre de tabulation du contrle dans son conteneur. Obtient ou dfinit une valeur indiquant si l'utilisateur peut octroyer le focus ce contrle l'aide de la touche TAB. Obtient ou dfinit une valeur indiquant si le contrle est affich.
Description
Quelques vnements : Avec le contrle bouton radio, seul l'vnement CheckedChanged prsente de l'intrt. Il est signal lorsqu'un bouton radio change d'tat. Evnement
Click (hrit de Control) CheckedChanged
Description
Se produit suite un clic sur le contrle. Il est gnralement gr lorsque la proprit AutoCheck vaut false. Se produit suite au changement d'tat du bouton radio.
65
Karim Kalti
La classe GroupBox
Cette classe reprsente un contrle groupe. Ce contrle est un conteneur qui permet de regrouper logiquement un ensemble de contrles de n'importe quel type. Les groupes sont gnralement utiliss pour regrouper des contrles de type "bouton radio". Les boutons radio d'un groupe sont mutuellement exclusifs. Des boutons radio appartenant un mme formulaire mais faisant partie de deux groupes diffrents fonctionnent de manire compltement indpendante. Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.GroupBox
Constructeur : public
GroupBox()
Quelques proprits : Outre les proprits hrites des classes de base et prsentes dans les paragraphes prcdents : Texte, Enabled, Location, Name, TabIndex, TabStop, Visible, etc, le contrle GroupBox possde une autre proprit intressante qui est Controls. Proprit
Controls
Type
ControlCollection
Description
C'est une collection qui comporte les contrles contenus dans le groupe.
Remarque : Comme toute collection, ControlCollection possde les mthodes usuelles Add, AddRange, Remove, RemoveAt, Cleat, Contains, IndexOf.
Description
Quelques vnements : Le GroupBox gre les vnements grs par les classes de base (click, etc), toutefois la gestion des vnements au niveau de ce contrle reste rare sur le plan pratique.
66
Karim Kalti
La classe ListBox
Cette classe reprsente une bote de liste d'articles. Ce contrle sert oprer une slection d'un ou de plusieurs articles partir de la liste. Hirarchie :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Control System.Windows.Forms.ListControl System.Windows.Forms.ListBox
ListBox();
Proprit
BorderStyle
Type
enum BorderStyle
Description
Type de contour. Les valeurs possibles sont None (aucun contour), FixedSingle (Contour form d'une simple ligne), Fixed3D (contour avec effet de relief). Indique la manire d'affichage de la liste. Les valeurs possibles de cette proprit sont : Normal (Affichage automatique, tous les articles ayant la mme hauteur), OwnerDrawFixed (bote de liste dont tous les articles ont la mme taille), OwnerDrawVariable (bote de liste dont tous les articles non pas la mme taille cause de l'utilisation de police de caractre diffrente par exemple). Indique si une barre de dfilement horizontale doit tre automatiquement ajoute si ncessaire. Hauteur d'un article. Par dfaut, la hauteur d'un article est de 13 pixels. Cette valeur est utilise dans le cas ou DrawMode prend la valeur OwnerDrawFixed.
DrawMode
enum DrawMode
HorizontalScrollBar ItemHeight
bool int
67
Karim Kalti
Items ScrollAlwaysVisible
Collection de libells d'articles. La valeur true force la barre de dfilement verticale tre affiche mme si tous les articles sont visibles. Mode de slection des articles. Les valeurs possibles sont : One (un seul article peut tre slectionn), None (aucun article ne peut tre slectionn), MultiSimple (Chaque clic slectionne un article supplmentaire), MultiExtended (slection multiple par les combinaisons avec MAJ et CTRL). Indique si les articles de la bote de liste doivent tre tris par ordre alphabtique.
SelectionMode
Sorted
Type
int SelectedIndex Collection Object SelectedObject Collection
Description
Index de l'article slectionn. (0 pour le premier). La valeur -1 indique qu'aucun article n'est slectionn. Collection d'indices des articles slectionns. Article slectionn. Cet article peut tre de n'importe quel type, il est toutefois dans la majorit des cas de type string. Collection d'articles slectionns.
Description
Dslectionne tous les articles slectionns. Renvoie l'index du premier article qui commence par la chane passe en argument. Indique si l'article dont l'index est pass en argument est slectionn ou non. Slectionne (Value=true) ou dslectionne (Value=false) l'article dont l'index est pass en argument.
Quelques vnements : Les vnements les plus souvent traits par les botes de liste sont : Click et DoubleClick : pour dtecter un clic ou un double-clic sur un article. KeyPress : gnralement pour dtecter une frappe de ENTREE sur un article slectionn. SelectedIndexChanged : pour dtecter le passage d'un article l'autre (par clic sur un article ou par les touches de direction du clavier).
68
Karim Kalti
Exemple 2 : L'exemple suivant suppose l'existence de deux listes listBox1 et listBox2. Suite la slection d'un article dans la premire liste, le programme le rcupre et cherche sa prsence dans la deuxime liste. Si cet article est prsent alors il sera galement slectionn dans la deuxime liste, sinon un message indiquant sont absence sera affich.
private void listBox1_SelectedIndexChanged(object sender, System.EventArgs e) { string ArticleCourant = listBox1.SelectedItem.ToString(); int index = listBox2.FindString(ArticleCourant); if(index == -1) MessageBox.Show("l'article est absent de la liste 2"); else listBox2.SetSelected(index,true); }
69
Karim Kalti
Il existe galement deux autres vnements trs frquemment utiliss qui sont Click et DoubleClick. La diffrence entre ces deux vnements d'une part et MouseDown ainsi que MouseUp d'autre part rside essentiellement dans les informations qui accompagnent l'occurrence de ces vnements.
L'vnement Click
Cet vnement a lieu lorsqu'un clic survient sur un contrle. Le contrle peut tre un objet de n'importe quel classe drive de la classe Control du .NetFrameWork (Exemple : Form, Button, TextBox, Label,). Evnement : public event EventHandler Click; Type dlgu : public delegate void EventHandler(Object sender, EventArgs e);
70
Karim Kalti
this.SuspendLayout(); // button1 this.button1.Location = new System.Drawing.Point(96,40); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(64, 24); this.button1.TabIndex = 0; this.button1.Text = "Message"; this.button1.Click+=new EventHandler(this.FTButton); // Form1 this.ClientSize = new System.Drawing.Size(292, 266); this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion void FTButton(Object sender, EventArgs e) {if(this.button1.Text=="Message1") this.button1.Text="Message2"; else this.button1.Text="Message1"; } static void Main() {Application.Run(new Form1());} }} Programme 2 : une autre criture du programme 1 namespace WindowsApplication3 { public class MyBt : Button { public MyBt() {// button1 this.Location = new System.Drawing.Point(96, 40); this.Name = "button1"; this.Size = new System.Drawing.Size(64, 24); this.TabIndex = 0; this.Text = "button1"; this.Click+= new EventHandler(this.FTButton); } void FTButton(Object sender, EventArgs e) { if(this.Text=="Message1") this.Text="Message2"; else this.Text="Message1"; }} public class Form1 : System.Windows.Forms.Form {private MyBt button1; public Form1() {InitializeComponent();} #region Windows Form Designer generated code private void InitializeComponent() { this.button1 = new MyBt(); this.SuspendLayout(); // Form1 this.ClientSize = new System.Drawing.Size(292, 266); this.Controls.Add(this.button1); this.Name = "Form1"; this.Text = "Form1"; this.ResumeLayout(false); } #endregion static void Main() {Application.Run(new Form1());} }}
Programme 3 : Traitement de deux vnements par une seule fonction public class Form2 : System.Windows.Forms.Form {private System.Windows.Forms.Button button1; private System.Windows.Forms.Button button2; public Form2() {InitializeComponent();} private void InitializeComponent()
71
Karim Kalti
{this.button1 = new System.Windows.Forms.Button(); this.button2 = new System.Windows.Forms.Button(); this.SuspendLayout(); // button1 this.button1.Location = new System.Drawing.Point(48, 48); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(80, 24); this.button1.TabIndex = 0; this.button1.Text = "button1"; this.button1.Click+=new EventHandler(this.FT); // button2 this.button2.Location=new System.Drawing.Point(144, 48); this.button2.Name = "button2"; this.button2.Size = new System.Drawing.Size(80, 24); this.button2.TabIndex = 1; this.button2.Text = "button2"; this.button2.Click+=new EventHandler(this.FT); // Form2 this.ClientSize = new System.Drawing.Size(272, 117); this.Controls.Add(this.button2); this.Controls.Add(this.button1); this.Name = "Form2"; this.Text = "Form2"; this.ResumeLayout(false); } void FT(Object sender, EventArgs e) { if(sender == this.button1) this.Text="Bouton1 est cliqu"; if(sender == this.button2) this.Text="Bouton2 est cliqu"; }}
L'vnement DoubleClick
Cet vnement a lieu lorsqu'un double clic survient sur un contrle. La dcision relative la distinction entre un double clic et deux clics successifs est faite par le systme d'exploitation. Cette dcision se base sur le temps qui spare les deux clics. Ce paramtre peut tre rgl travers le panneau de configuration de Windows. Evnement : public event EventHandler DoubleClick; Type dlgu : public delegate void EventHandler(Object sender,
EventArgs e);
Remarque : Si un contrle est capable de grer la fois les vnements Click et DoubleClick (exemple Form) alors un double clic sur ce contrle va dclencher automatiquement et dans l'ordre l'vnement Click suivi de l'vnement DoubleClick.
72
Karim Kalti
Spcification: Proprit Button Clicks Delta X Y Type Enum MouseButtons int int int int Description Indique quel bouton de la souris est enfonc. Les valeurs possibles de lnumration MouseButtons sont {Left, Midle, None, Right,} Indique le nombre de fois le bouton de la souris a t appuy puis relch. Nombre de dtente sur la molette (si la souris en possde une) Coordonn X par rapprot laire client. Laxe des x est orient de gauche vers la droite partir du coin suprieur gauche. Coordonn Y. Laxe des y est orient du haut vers le bas partir du coin suprieur gauche.
Exemple : Affichage des coordonnes de la souris suite l'appui sur l'un de ses boutons (la souris survole un formulaire).
// this rfrence le formulaire this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.FT); // FT est une mthode de la classe qui reprsente le formulaire void FT(object sender, System.Windows.Forms.MouseEventArgs e) { MessageBox.Show("X: "+e.X+", Y :"+e.Y); }
73
Karim Kalti
Spcification : Proprit Alt Control Handled Shift KeyCode Valeur true, false true, false true, false true, false Enum Keys Description Indique si la touche Alt est enfonce Indique si la touche Ctrl est enfonce Indique que lvnement a t trait Indique si la touche Maj est enfonce Une des valeurs de lnumration Keys
Pour avoir la spcification complte de la classe KeyEventArgs, il faut consulter la documentation du .NetFramework Exemples de valeurs de l'numration Keys Les touches de F1 F24 correspondent Keys.Fi (exemple : la valeur Keys.F5 correspond la touche F5). Les valeurs Keys.D0 jusqu Keys.D9 correspondent aux touches numriques. Les valeurs Keys.A jusqu' Keys.Z correspondent aux touches alphabtiques. Keys possde d'autres valeurs qui correspondent aux touches spciales du clavier. Comme exemple de ces valeurs, il est possible de citer : Keys.Back, Keys.Cancel, Keys.Home, Keys.End, Keys.Del, etc.
La liste complte des valeurs de l'numration Keys peut tre consulte dans la documentation du .NetFrameWork. Exemple : Manipulation du paramtre e dans une fonction de traitement d'un vnement KeyUp ou KeyDown Si on veut vrifier si lutilisateur a appuy en mme temps sur la touche MAJ et sur le bouton de dplacement vers la gauche, alors la condition de test doit tre comme suit :
void FT(object sender, System.Windows.Forms.KeyEventArgs e) { if(e.Shift== true && e.KeyCode==Keys.Left) { // Mettre le code de traitement ici } }
Exemple d'inscription dune fonction de traitement auprs du gestionnaire d'un vnement KeyUp This.KeyUp += new System.Windows.Forms.KeyEventHandler(FT) Remarque : Aucune distinction nest faite entre les minuscules et les majuscules par les vnements KeyUp et KeyDown : e.KeyCode==Keys.A est vraie pour 'A' et 'a'. Pour intercepter les vnements au niveau de la fentre il faut que la proprit KeyPreview de cette fentre soit mise true.
Lvnement KeyPress
Evnement : public event KeyPressEventHandler KeyPress; Type dlgu :
public delegate void KeyPressEventHandler(Object sender, KeyPressEventArgs e);
74
Karim Kalti
Exemple : Si on veut tester si le caractre tap est alors la condition de test doit tre la suivante : if(e.KeyChar == '')
Remarques : I'vnement KeyPress fait la distinction entre minuscule et majuscule. Gnralement les vnements KeyUp et KeyDown sont utiliss pour dtecter les touches de direction, les touches de fonctions et les touches spciales du clavier comme par exemple Del, Back, KeyPress est utilis pour traiter les vnements lis aux touches alphanumriques.
75
Karim Kalti
Les menus
Exemple de menu
La classe MainMenu
Un menu en .NET est reprsent par le contrle MainMenu. Ce contrle reprsente en ralit la structure qui contient le menu. En mode programmation, ce contrle est cr travers la classe qui porte le mme nom "MainMenu".
Hirarchie de la classe :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Menu System.Windows.Forms.MainMenu
Quelques proprits : Proprit Container (hrit de Component) Handle IsParent MdiListItem MenuItems Description Obtient une rfrence au conteneur du composant. Obtient une valeur qui reprsente le handle de la fentre contenant le menu. Obtient une valeur indiquant si ce menu contient des lments de menu. Le MainMenu joue dans ce cas le rle de parent pour ces lments de menu. Cette proprit est en lecture seule. Obtient une valeur qui indique le MenuItem utilis pour afficher une liste de formulaires enfants MDI. Obtient une valeur qui indique la collection d'objets MenuItem associe au menu.
La classe MenuItem
Un Menu est gnralement compos d'un ensemble de contrles appels lments de menu. Chaque lment de menu est reprsent par la classe MenuItem. Hirarchie de la classe :
System.Object System.MarshalByRefObject System.ComponentModel.Component System.Windows.Forms.Menu System.Windows.Forms.MenuItem
76
Karim Kalti
Quelques proprits : Proprit Valeur Desciption Obtient ou dfinit une valeur qui indique si MenuItem est plac sur une nouvelle ligne (pour un lment de menu ajout un objet MainMenu) ou dans une nouvelle colonne (pour un lment de sous-menu ou un lment de menu affich dans ContextMenu). Obtient ou dfinit une valeur qui indique si l'lment est plac sur une nouvelle ligne (pour un lment de menu ajout un objet MainMenu) ou dans une nouvelle colonne (pour un lment de menu ou un lment de sous-menu affich dans un ContextMenu). Obtient ou dfinit une valeur qui indique si une coche apparat en regard du texte de l'lment de menu. Obtient le IContainer qui contient Component. Obtient ou dfinit une valeur indiquant si l'lment est l'lment de menu par dfaut. Obtient ou dfinit une valeur qui indique si l'lment de menu est activ. Obtient une valeur qui reprsente le handle de fentre pour le menu. Obtient ou dfinit une valeur qui indique la position de l'lment de menu dans son menu parent. Substitu. Obtient une valeur qui indique si l'lment de menu contient des lments de menu enfants. (sous menu) Obtient ou dfinit une valeur qui indique si l'lment de menu va tre rempli avec une liste des fentres enfants MDI (interface multidocument) affiches dans le formulaire associ. Obtient une valeur qui indique le MenuItem utilis pour afficher une liste de formulaires enfants MDI. Obtient une valeur qui indique la collection d'objets MenuItem associe au menu. Obtient ou dfinit une valeur qui indique la position relative de l'lment de menu lorsqu'il est fusionn avec un autre. Obtient ou dfinit une valeur qui indique le comportement de l'lment de menu lorsque son menu est fusionn avec un autre. Obtient une valeur qui indique le caractre mnmonique associ cet lment de menu. Obtient ou dfinit une valeur qui indique si l'lment de menu est dessin par le code que vous fournissez ou par Windows. Obtient une valeur indiquant le menu qui contient cet lment de menu. Obtient ou dfinit une valeur qui indique si le MenuItem affiche une case d'option au lieu d'une coche lorsqu'il est activ. Obtient ou dfinit une valeur qui indique la touche de raccourci associe l'lment de menu. Obtient ou dfinit une valeur qui indique si la touche de raccourci associe l'lment de menu est affiche en regard de la lgende de l'lment de menu. Obtient ou dfinit le ISite de Component. Obtient ou dfinit une valeur qui indique la lgende de l'lment de menu. Obtient ou dfinit une valeur qui indique si l'lment de menu est visible.
BarBreak
Break
Checked Container (hrit de Component) DefaultItem Enabled Handle (hrit de Menu) Index IsParent MdiList MdiListItem (hrit de Menu) MenuItems (hrit de Menu) MergeOrder MergeType Mnemonic OwnerDraw Parent RadioCheck Shortcut ShowShortcut Site (hrit de Component) Text Visible
T/F
T/F
int
string
77
Karim Kalti
Pour qu'un menu principal (MainMenu) soit affich sur un formulaire (Form), il faut qu'il soit affect la proprit Menu du formulaire. Pour qu'un lment de menu (MenuItem) soit affich dans un menu principal (MainMenu), il faut qu'il soit ajout la liste des MenuItems du menu principal. Le menu principal joue dans ce cas le rle de parent ou de conteneur pour l'lment de menu. Un lment de menu (MenuItem) peut jouer galement le rle de parent pour un sous-menu compos lui aussi de plusieurs lments de menu. Pour que ce menu soit affich, il faut que ses lments soient ajouts la liste des MenuItems de l'lment parent.
Exemple 1:
// Mthode membre de la classe qui reprsente le formulaire public void CreateMyMainMenu() { // Cration d'un MainMenu vide. MainMenu mainMenu1 = new MainMenu(); MenuItem menuItem1 = new MenuItem(); MenuItem menuItem2 = new MenuItem(); menuItem1.Text = "File"; menuItem2.Text = "Edit"; // Ajout de deux lments de menu au menu principal. mainMenu1.MenuItems.Add(menuItem1); mainMenu1.MenuItems.Add(menuItem2); // Attachement du menu principal au formulaire. // this rfrence le formulaire this.Menu = mainMenu1; } private void InitializeComponent() { //L'appel de CreateMyMainMenu CreateMyMainMenu(); }
Rsultat de l'exemple 1
Exemple 2:
// Mthode membre de la classe qui reprsente le formulaire public void CreateMyMenu() { MainMenu mainMenu1 = new MainMenu(); MenuItem menuItem1 = new MenuItem(); MenuItem menuItem2 = new MenuItem(); MenuItem menuItem3 = new MenuItem(); MenuItem menuItem4 = new MenuItem(); menuItem1.Text = "&Edit"; menuItem2.Text = "Font Size"; menuItem3.Text = "Small"; menuItem3.Checked = true; menuItem3.Shortcut = Shortcut.CtrlS; menuItem4.Text = "Large"; menuItem4.Shortcut = Shortcut.CtrlL; menuItem4.Index = 1; menuItem2.MenuItems.Add(menuItem3); menuItem2.MenuItems.Add(menuItem4); menuItem1.MenuItems.Add(menuItem2); mainMenu1.MenuItems.Add(menuItem1); this.Menu = mainMenu1; }
Rsultat de l'exemple 2
78
Karim Kalti
EventArgs e);
L'vnement PopUp Cet vnement se produit avant l'affichage de la liste des lments de menu d'un lment de menu. Cet vnement est gnralement utilis pour faire des modifications des paramtres du menu (activation, dsactivation,) suivant les donnes du programme. Evnement: public event EventHandler Popup; Type dlgu: public delegate void EventHandler(object sender,
EventArgs e);
Changement du menu principal suivant l'tat du programme Il suffit de crer plusieurs menus principaux (MainMenu) et d'affecter l'un d'eux la proprit Menu du formulaire et ce suivant l'tat de l'excution du programme.
79
Karim Kalti
Rappel
Terminologie API (Application Programming Interfaces) : une API est une bibliothque de modles de fonctions (interfaces) gnralement de bas-niveau ralisant une tche bien prcise. Dans un contexte orient objet, une API se prsente comme une bibliothque de classes interfaces disposant de mthodes permettant de raliser des tches bas-niveau. API d'accs aux donnes : Une API d'accs aux donnes est une bibliothque de fonctions ou d'objets permettant de faire les oprations d'accs aux bases de donnes, d'interrogation de ces bases (envoi des requtes) et de rcupration de donnes partir de ces bases. API native d'accs aux donnes : Chaque SGBD possde une API propritaire tenant compte de ses spcificits et qui permet de faire les oprations d'accs cet SGBD. Une telle API est appele une API native. ODBC (Open Data Base Connectivity) ODBC (Open Data Base Connectivity) est une API de fonctions (non oriente objet) unifie d'accs aux donnes qui a pour objectif de permettre l'accs n'importe quel SGBD sans ncessiter une connaissance des API natives.
Requte utilisateur (API native)
SGBD SQLServe
Pont ODBC
SGBD Oracle
SGBD Access
Requte utilisateur (API native)
SGBD X
Architecture d'un pont ODBC : Un pont ODBC est compos de trois couches : La premire couche est une couche de rception des requtes adresses par les applications un SGBD. Ces requtes sont spcifies par les applications l'aide de l'API ODBC. La deuxime couche est constitue d'un composant logiciel appel gestionnaire de pilotes. Ce gestionnaire joue le rle d'intermdiaire qui va dcider du choix du pilote ODBC appropri qui va prendre en charge la requte adresse par l'application. Ce choix se base sur le type de la base de donnes interroge. Le
80
Karim Kalti
gestionnaire assure le chargement en mmoire et la libration du pilote slectionn. La troisime couche assure la communication entre le gestionnaire des pilotes et les pilotes ODBC. Cette communication est faite travers des appels effectus par le gestionnaire, aux fonctions des pilotes ODBC. Ces fonctions font partie de l'API unifie dfinie par le standard ODBC et utilise par les dveloppeurs des pilotes ODBC.
Pilote ODBC
Pilote ODBC
Pilote ODBC
Pilote ODBC
SGBD 1
SGBD 2
SGBD 3
SGBD 4
Pilote ODBC Un pilote ODBC est un composant logiciel qui a pour objectif de traduire la requte crite avec l'API ODBC unifie vers un format (crit l'aide de l'API native) propre au SGBD interrog. Tout SGBD qui veut tre accessible travers ODBC doit fournir un pilote ODBC qui lui est spcifique. Ainsi par exemple, pour accder une base de donnes SQLServer ou Oracle travers ODBC, il faut installer sur la machine sur laquelle tourne l'application le pilote ODBC pour SQL Server, respectivement pour Oracle. Pour voir sous Windows XP la liste des pilotes ODBC installs sur une machine il faut aller : Panneau de configuration Outils d'administration Sources de donnes ODBC OLE DB : OLE DB (Open Linking and Embeding for DataBases) est une API unifie d'accs aux donnes qui offre plus de possibilits que l'API ODBC. En effet ODBC permet l'accs aux bases de donnes relationnelles seulement. Avec OLE DB il est possible d'accder n'importe quelle source de donnes, relationnelle ou non (Systme de fichiers, XML, Tableur, Messagerie,). OLE DB utilise une collection d'objets qui dfinit un modle diffrent de celui de ODBC. Ce modle s'articule autour des objets de base suivants : Data Source, Session, Command, Rowset. A ces objets de base s'ajoutent d'autres objets qui sont : Enumerator, Transaction, Error.
81
Karim Kalti
SGBD-R
XML
API OLE DB
Pont OLE DB
Fichiers
Tableur
Autres
Avantages et inconvnients de l'utilisation des APIs unifies. Sans l'utilisation d'une API unifie, les programmeurs d'applications sont obligs d'appendre diffrentes API natives pour faire des accs diffrents SGBDs. Ceci alourdit la charge de travail des dveloppeurs surtout dans les milieux professionnels o l'on est amen souvent travailler sur des SGBD diffrents d'un projet un autre. L'intrt des APIs unifies dans ce cas est grand puisqu'elles vont allger la charge de travail des dveloppeurs. Les APIs unifies sont toutefois moins rapides que les API natives cause notamment des tapes de conversion de requtes qui sont ncessaires dans ce cas.
Prsentation de ADO.NET
ADO.NET (ActiveX Database Object) est une nouvelle API d'accs aux donnes propose par Microsoft. Cette API permet aux applications dveloppes en .NET de travailler avec diffrents types de sources de donnes. Caractristiques : ADO.NET permet de travailler en mode connect et en mode dconnect. ADO.NET permet de travailler d'une manire compltement indpendante du type de la base de donnes. ADO.NET permet l'interoprabilit avec d'autres sources de donnes (relationnelle ou non telles que les systmes de fichiers, Active Directory, etc.). Cette interoprabilit est obtenue grce la possibilit d'importer et d'exporter les donnes au format XML. Configuration requise pour ADO.NET ADO.NET est fourni avec le FrameWork.NET. Il est ncessaire par ailleurs d'installer MDAC (Microsoft Data Access Components version 2.6 ou plus) pour pouvoir utiliser les fournisseurs de donnes SQL Server ou OLE DB. ADO.NET peut tre utilis sous Windows CE/95/98/ME/NT4 SP6a/2K/XP/2003 Server.
82
Karim Kalti
Le mode connect Ce mode permet de travailler d'une manire connecte par rapport la source de donnes. Les tapes de travail avec ce mode se droulent comme suit : Le client effectue une requte auprs du serveur (Exemple un SELECT). Le serveur calcule le rsultat de la requte, il maintient une communication logique avec le client et lui envoie le rsultat de son SELECT ligne par ligne suite aux demandes de ce client (dplacement entre les enregistrements de son RecordSet). Le serveur doit savoir o il en est dans sa communication avec chaque client qui lui est connect. Comparaison des deux modes Le mode dconnect est plus adapt la manire de travailler sur Internet. En effet sur Internet on ne peut pas connatre quand est ce que le client (lger dans ce cas) dcide de se dconnecter de la page d'accs aux donnes (Il peut la laisser ouverte et passer dautres pages). Maintenir plusieurs connexions ouvertes en continue avec la source de donnes constitue un frein la capacit de monte en charge d'une application. (ce problme peut toutefois tre vit en utilisant la proprit TimeOut lie la variable de Session). Le mode dconnect engendre une plus grande surcharge du rseau mais seulement au moment de la transmission du rsultat de la requte ce qui risque de provoquer des courts blocages. Le mode connect est prfr lorsque le jeu d'enregistrement traiter est trop grand pour tre facilement transfr et stock localement en mmoire.
Les deux couches qui composent ce modle sont : Une couche connecte qui comporte des classes manages qui font des accs physiques la base de donnes. Ces classes constituent ce que ADO.NET appelle un fournisseur de donnes ou Data Provider (Connection, Transaction, Command, Parameters, DataReader, DataAdapter,). Une couche dconnecte qui comporte des classes qui ne sont pas en liaison directe avec les bases de donnes. Ces classes constituent une sorte de cache pour le stockage en local d'une partie des donnes de la base.
83
Karim Kalti
Description
Etablit une connexion une source de donnes spcifique. Excute une commande adresse une source de donnes. Lit un flux partir d'une source de donnes. Seule la lecture est possible. Elle est faite dans un sens unique (vers l'avant). Remplit un DataSet partir d'une source de donnes et met jour cette dernire partir d'un DataSet.
A ces classes de base viennent s'ajouter d'autres qui les compltent : Objet
Transaction CommandBuilder Parameter Exception Error
Description
Permet de lister les commandes dans une transaction. Un assistant qui gnre automatiquement les proprits des commandes d'un DataAdapter. Dfinit les entres, les sorties et retourne les valeurs des paramtres pour les commandes et les procdures stockes. Exception retourne lorsqu'une erreur est rencontre au niveau de la source de donnes. Pour une erreur rencontre au niveau du client le fournisseur de donnes intercepte une exception du FrameWork.NET. Expose les informations accompagnant un avertissement ou une erreur retourn(e) par une source de donnes.
Les classes susmentionnes ne sont pas directement instanciables. Elles sont en effet dfinies dans le FrameWork .NET sous forme d'interfaces (car elles dfinissent un modle). Par exemple l'objet Connection est reprsent par l'interface IDbConnection, l'objet DataAdpater est reprsent par l'interface IDbDataAdapter, l'objet Command est reprsent par l'interface IDbCommand et l'objet DataReader est reprsent par l'interface IDbDataReader.
84
Karim Kalti
Remarque 1: Tout SGBD qui se veut accessible d'une manire native travers une application .NET doit proposer sa propre implmentation du modle des fournisseurs de donnes (son propre pilote ADO.NET). Remarque 2 : Chaque classe qui implmente une interface faisant partie d'un fournisseur porte le nom de cette interface prfix du nom du fournisseur auquel elle appartient. Le tableau suivant donne quelques exemples de noms de classes implmentes par les diffrents fournisseurs :
Interface
Connection Command DataReader DataAdapter
OLE DB Provider
OleDbConnection OleDbCommand OleDbDataReader OleDbDataAdapter
ODBC Provider
ODBCConnection ODBCCommand ODBCDataReader ODBCDataAdapter
SQL Provider
SqlConnection SqlCommand SQLDataReader SqlDataAdapter
Oracle Provider
OracleConnection OracleCommand OracleDataReader OracleDataAdapter
Fournisseur SQL-Server API ADO.NET Fournisseur ORACLE Fournisseur OLEDB Fournisseur ODBC
SQL Server
Pont OLEDB
MS-ACCESS
API ODBC
Pont ODBC
Autres SGBD
Le reste de ce chapitre prsente les diffrentes tapes de l'accs une base de donnes l'aide du fournisseur OLEDB Provider. L'accs l'aide des autres fournisseurs se fait de la mme manire puisque tous les fournisseurs implmentent le mme modle.
Constructeurs : Constructeur
OLeDbConnection() OleDbConnection(string connectionString)
Description
Cre un objet de connexion non initialis. Cre un objet de connexion tout en spcifiant une chane de connexion. Ce constructeur dcortique automatiquement la chane pour remplir les proprits de lobjet de connexion.
85
Karim Kalti
Type
string
Description
Il sagit dune chane de caractres au format bien particulier qui est passe au constructeur de lobjet de connexion. Ce constructeur la place dans l'attribut courant et la dcortique pour initialiser les autres attributs de la classe. Il est noter que certains attributs sont en lecture seule et ne peuvent tre initialise en dehors du constructeur de la classe et donc travers la chane de connexion. Dure en secondes durant laquelle ltablissement dune connexion au serveur de BD est tent. Si pendant ce laps temps la connexion choue alors une erreur est signale. Une valeur nulle indique une attente infinie ( viter). Par dfaut la valeur est de 15 secondes. Nom de la base de donnes ( utiliser avec SQL Server). Nom de la source de donnes ( utiliser dans le cas de MSACCESS ou autres). Mot de passe pour accder la base Identificateur du type de la BD
Description
Ouverture explicite de la base. Une exception est gnre en cas dchec de louverture. Fermeture explicite de la base de donnes.
Spcification de la valeur de la proprit DataSource : La valeur de la proprit DataSource dsigne le chemin de la source de donnes. Ce chemin peut tre : Un chemin absolu. (Exemple : data source = C:\repertoire\MaBase.mdb) Un chemin relatif si la source se trouve dans le mme dossier que lexcutable de lapplication ou si elle se trouve dans un sous dossier de celui-ci. (Exemple pour un mme dossier : data source = MaBase.mdb) Un chemin rseau si la source se trouve sur une autre machine du rseau local. (Exemple: data source = \\machine\Lecteur\...\ MaBase.mdb) Spcification de la valeur de la proprit Provider : Cette proprit dsigne le type de la source de donnes laquelle est fait l'accs. Le tableau ci-dessous donne quelques exemples de valeurs utilises pour un certain nombre de SGBD.
SGBD
Access SGL Server AS400 DB2 Fox Pro Oracle
Valeur
Provider = Microsoft.Jet.OLEDB.4.0 Provider =SQLOLEDB Provider = IBMA400 ; Provider = DB2OLEDB ; Provider = vfpOLEDB ; Provider = MSDAORA
86
Karim Kalti
Commentaire : Suite la cration de l'objet de connexion, l'tablissement effectif de la liaison avec la base est amorc par l'appel la mthode Open. Une fois la connexion ouverte, il devient possible d'adresser la base des requtes de diffrents types (insertion, slection, ). Enfin, lorsque l'interrogation se termine, il faut fermer la connexion avec la mthode Close. Remarque : utilisation de @ devant la chane de connexion Par dfaut le caractre '\' introduit dans les chanes un caractre de formatage. Pour ne pas le considrer ainsi, il faut faire prcder la chane de @. Si non lorsquil sagit de spcifier un chemin, il faut utiliser \\ au lieu de \. Dans ce cas la chane de connexion devient :
"Provider=Microsoft.Jet.OleDb.4.0 ; Data Source = C:\\Repertoire\\MaBase.mdb";
Description
Cre un objet de commande non initialis Cre une commande et lui passe une requte SQL. Cre une commande et lui passe une requte SQL plus un objet de connexion.
Description
CommandType
enum CommandType
CommandText
string
Indique le type de la commande. Trois valeurs sont possibles dans ce cadre : Text : Signifie que la commande est une requte SQL. StoredProcedure : signifie que la commande reprsente un appel une procdure stocke. TableDirect : signifie que la commande est une requte de slection du contenu entier d'une table. Contient le texte de la commande. La manire d'interprtation de ce texte dpend de la valeur de la proprit CommandType. Si CommandType = Text alors CommandText reprsente le texte de la requte SQL. Si CommandType=StoredProcedure alors CommandText contient le nom de la procdure stocke qui sera appele. Si CommandType=TableDirect alors CommandText contient le nom de la table dont le contenu sera renvoy. Cette commande est quivalente une requte SLECT * applique la table en question. Nombre de secondes dattente avant quune commande ne soit dclare en erreur. La valeur par dfaut est de 30 sec. Lobjet connexion associ la commande. Il sert spcifier la source de donnes laquelle est destine la commande. Liste des paramtres utiliss par la commande. Par dfaut cette collection est vide.
Principales mthodes de OleDbCommand : Les mthodes les plus utilises de la classe OleDbCommand sont celles qui permettent d'excuter les commandes. Trois mthodes sont proposes cet effet : Mthode Description
Elle excute la commande spcifie dans CommandText. Dans ce cas la commande doit tre une commande dinsertion, de mise jour ou de suppression (INSERT, UPDATE, DELETE). La mthode retourne le nombre de lignes sur lesquelles a port la commande (nombre de lignes insres, supprimes, mises jour). La mthode ExecuteNonQuery ne peut pas excuter une commande de slection (SELECT). Elle retourne -1 dans ce cas.
int ExecuteNonQuery()
87
Karim Kalti
object ExecuteScalar()
OleDbDataReader ExecuteReader()
Cette mthode est essentiellement utilise pour excuter une commande qui renvoie une valeur scalaire (Exemple : SELECT COUNT* ). D'une manire gnrale, ExecuteScalar renvoie sous la forme dune valeur de type object la premire colonne de la premire ligne de la collection d'enregistrements reprsentant le rsultat de la requte. Elle retourne une rfrence nulle si ce rsultat est vide. Cette mthode est utilise lorsque la commande renvoie une collection d'enregistrements (Gnralement le rsultat d'une requte de slection). La collection d'enregistrements renvoye est place dans un objet de type OleDbDataReader (implmentation de l'interface DataReader). Cet objet permet de faire le parcours des enregistrements un par un, en lecture seule et dans un seul sens (vers l'avant).
L'objet OleDbParameter
Un objet Parameter reprsente un paramtre d'une commande. Il est noter qu'un objet Command peut comporter une collection de paramtres stocke dans sa proprit Parameters. Pour le fournisseur OleDb les paramtres sont crs l'aide de la classe OleDbParameter. Proprit
ParameterName
Type
string enum ParameterDirection OleDbType Bool Byte
Description
Nom du paramtre. - Input : le paramtre est un paramtre d'entre. - Output : le paramtre est un paramtre de sortie. - InputOutput : le paramtre est un paramtre d'entre et de sortie. - ReturnValue : le paramtre reprsente la valeur de retour (gnralement d'une procdure stocke). Le type du paramtre. Indique si le paramtre accepte la valeur null ou non (par dfaut false). Obtient ou dfinit le nombre maximal de chiffres utiliss pour reprsenter la proprit Value. (la valeur par dfaut est 0, elle signifie que c'est le fournisseur qui dtermine la prcision) Obtient ou dfinit le nombre de dcimales (chiffres aprs la virgule) appliqu la rsolution de Value. La proprit Scale est utilise uniquement pour les paramtres d'entre dcimaux et numriques. (la valeur par dfaut est 0, elle signifie que c'est le fournisseur qui dtermine la valeur de cette proprit). Obtient ou dfinit la taille maximale, en octets, des donnes figurant dans la colonne. Elle est utilise essentiellement pour les chanes de caractres. Pour les types de taille fixe cette valeur est tout simplement ignore. Obtient ou dfinit le nom de la colonne source mappe DataSet et utilise pour charger et retourner Value. Obtient ou dfinit la version de la ligne utiliser lors du chargement de Value. Obtient ou dfinit la valeur du paramtre.
Direction
Scale
Object
public OleDbParameter(string parameterName, OleDbType oleDbType, int size, ParameterDirection direction, bool isNullable, byte precision, byte scale, string srcColumn, DataRowVersion srcVersion, object value);
Utilisation des espaces rserves dans les requtes Il est possible de faire passer des paramtres au texte SQL d'une requte et ce en utilisant des espaces rservs introduits par le caractre "?". Les espaces rservs ne sont pas accepts par tous les SGBD (Certains SGBDs demandent des paramtres nomms comme SQL Server par exemple). Les espaces rservs d'une requte prennent leurs valeurs partir de la collection des paramtres de l'objet Command qui reprsente cette requte. La correspondance entre les espaces et les paramtres se fait sur la base de l'ordre d'apparition des "?" dans le texte de la requte et de l'ordre d'ajout des paramtres la collection Parameters de l'objet Command. Ainsi, le premier paramtre ajout la collection correspond au premier espace rserv, le deuxime paramtre au deuxime espace rserv, etc. Au moment de l'excution de la commande, les espaces rservs de la requte seront remplacs par le contenu des proprits Value des objets paramtres qui leurs correspondent.
88
Karim Kalti
Exemple : Si on considre le texte de la requte suivante : "INSERT INTO NomTable Values (?, ?, ?)". L'objet command bas sur cette requte peut faire passer cette dernire des arguments qui prendront la place des espaces rservs. Ces arguments doivent provenir de la collection Parameters de cet objet Command.
Type
int []
Description
Nombre de champs dans lenregistrement renvoy (nombre de colonnes dans la ligne). Indexeur daccs aux champs de l'enregistrement courant de lobjet OleDbDataReader. Il peut tre index sur le numro du champ ou sur le nom du champ.
Description
Ferme lobjet OleDbDataReader. Renvoie le nom du nime champ. Renvoie la position dun champ dont le nom est pass comme argument. Une exception est gnre si le nom du champ nest pas connu. Renvoie true si le champ en nime position contient une valeur nulle. Lit la ligne suivante dans la table reprsentant la collection d'enregistrements. Read renvoie true si une ligne a effectivement pu tre lue. Elle renvoie false quand la fin du rsultat du SELECT est atteinte. Permet de passer directement l'enregistrement suivant (ligne suivante de la table). Renvoie true si cette ligne existe. Remplit le tableau en argument avec le contenu des diffrentes colonnes dune ligne (le contenu de l'enregistrement rfrenc par le DataReader). Elle renvoie le nombre de cellules remplies dans ce tableau. Si le tableau contient un nombre n de cellules infrieur au nombre de champs alors seules les n cellules sont remplies.
int GetValues(Object[])
Ouvrage
Champ Type
Inventaire Entier
Titre Chane
Auteur Chane
89
Karim Kalti
Exemple 1 : requte renvoyant une valeur (Calcul du nombre d'ouvrages) Le calcul du nombre d'ouvrages se fait l'aide d'une requte qui retourne une valeur de type scalaire (entier). C'est la mthode ExecuteScalar de l'objet Command qui doit alors tre utilise :
using System; using System.Data; using System.Data.OleDb; class DataAccess { static int CalculNbOuvrages() { // Cration de la chane de connexion string StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\ADO\ Biblio.mdb"; // Cration de l'objet de connexion OleDbConnection cnn = new OleDbConnection(StrCnn); // Ouverture de la connexion cnn.Open(); // Cration du texte de la commande string StrSql = "SELECT Count(*) FROM Ouvrage"; // Cration de l'objet Command OleDbCommand cmd=new OleDbCommand(StrSql,cnn); // Excution de la commande int n =(int)cmd.ExecuteScalar(); // Fermeture de la connexion cnn.Close(); return n; } static void Main() { Console.WriteLine("le rsultat est "+CalculNbOuvrages()); Console.ReadLine(); } }
Exemple 2 : Requte d'insertion dans une table (Ajout d'un ouvrage) L'insertion d'un enregistrement dans une table se fait gnralement l'aide de la mthode ExecuteNonQuery de l'objet Command.
using System; using System.Data; using System.Data.OleDb; class DataAccess { static int CalculNbOuvrages(){...} static void AjoutOuvrage() { // Cration de la chane de connexion string StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\ADO\Biblio.mdb"; // Cration de l'objet de connexion OleDbConnection cnn = new OleDbConnection(StrCnn); // Ouverture de la connexion cnn.Open(); // Texte de la commande string StrSql = "INSERT INTO Ouvrage VALUES (12,'Programmation C','Didier Le Blanc', #10/12/1999#)"; // Cration de l'objet Command OleDbCommand cmd=new OleDbCommand(StrSql,cnn); // Excution de la commande cmd.ExecuteNonQuery();
90
Karim Kalti
// Fermeture de la connexion cnn.Close(); } static void Main() { Console.WriteLine("le rsultat est "+CalculNbOuvrages()); AjoutOuvrage(); Console.WriteLine("le rsultat est "+CalculNbOuvrages()); Console.ReadLine(); } }
Exemple 3 : Requte de suppression et de mise jour Les requtes de suppression et de mise jour s'excutent de la mme manire que la requte d'insertion ( l'aide de la mthode ExecuteNonQuery). Il suffit tout simplement de changer le texte de la requte. Exemple de texte d'une commande de mise jour :
string StrSql = "UPDATE Ouvrage SET Titre = 'Programmation Java' WHERE Inventaire = 12";
Exemple 4 : Requte de slection L'excution d'une requte de slection se fait l'aide de la mthode ExecuteReader de l'objet Command. La collection d'enregistrements renvoye est place dans un objet DataReader. C'est travers cet objet que se fait la consultation de ces enregistrements.
using System; using System.Data; using System.Data.OleDb; class DataAccess { static void ConsultationOuvrage() { // Cration de la chane de connexion string StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\ADO\Biblio.mdb"; // Cration de l'objet de connexion OleDbConnection cnn = new OleDbConnection(StrCnn); // Ouverture de la connexion cnn.Open(); // Texte de la commande string StrSql = "SELECT * FROM Ouvrage"; // Cration de l'objet Command OleDbCommand cmd=new OleDbCommand(StrSql,cnn); // Execution de la commande et rcupration des donnes dans un DataReader OleDbDataReader rd = cmd.ExecuteReader(); // Parcours des enregistrements renvoys string s; int i =0; if(rd!=null) { while (rd.Read()) { s = (string)rd["Titre"]; // (string)rd[1] i+=1; Console.WriteLine("Ouvrage"+i+":"+s); } } // Fermeture de la connexion cnn.Close(); } static void Main() { ConsultationOuvrage(); Console.ReadLine(); } }
91
Karim Kalti
Requte paramtre
On considre dans ce qui suit la requte de slection de livres prsente au paragraphe prcdent. Supposons que l'on veuille slectionner seulement les livres dont l'anne d'dition est ultrieure une anne saisie par l'utilisateur. Le texte de la requte doit dans ce cas tre construit d'une manire dynamique. Deux solutions se prsentent cet gard. Solution 1 : Construction de la requte par concatnation. Dans cette solution, les donnes saisies par l'utilisateur sont converties en chanes de caractres et introduites dans le texte de la requte par concatnation comme le montre l'exemple suivant : Exemple :
int Anne; string StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source =C:\Data\Bilbio.mdb"; OleDbConnection cnn = new OleDbConnection(StrCnn); cnn.Open(); // Saisie de l'anne de rfrence Console.WriteLine("Donner l'anne de rfrence"); Anne=Int32.Parse(Console.ReadLine()); // Cration du texte de la requte par concatnation string StrSql = "SELECT * FROM Ouvrage WHERE [Anne d'dition]>"+Anne.ToString(); // Cration d'une commande base sur la requte de slection OleDbCommand cmd=new OleDbCommand(StrSql,cnn); OleDbDataReader rd = cmd.ExecuteReader();
Solution 2 : Utilisation des objets Parameters L'ADO.NET propose une alternative permettant d'automatiser le passage de paramtres aux requtes. Cette alternative se base sur l'utilisation des espaces rservs et des objets Parameters. L'exemple suivant illustre l'utilisation de cette technique : Exemple :
int Anne; string StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source =C:\Data\Bilbio.mdb"; OleDbConnection cnn = new OleDbConnection(StrCnn); cnn.Open(); // Saisie de l'anne de rfrence Console.WriteLine("Donner l'anne de rfrence"); Anne=Int32.Parse(Console.ReadLine()); // Texte de la requte avec utilisation d'un espace rserv permettant // de faire passer une anne d'dition comme argument string StrSql = "SELECT * FROM Ouvrage WHERE [Anne d'dition]>?"; // Cration d'un objet command bas sur la requte de slection OleDbCommand cmd=new OleDbCommand(StrSql,cnn); // Cration d'un objet Parameter qui va servir pour faire passer l'anne. // Il suffit de passer l'anne la proprit Value de l'objet Parameter OleDbParameter Par = new OleDbParameter("PDate",Anne); // Ajout du paramtre la liste des paramtres de la commande cmd.Parameters.Add(Par); // Excution de la commande OleDbDataReader rd = cmd.ExecuteReader();
92
Karim Kalti
DataSet
Remplissage
DataTable DataTable
Lecture des donnes
DataAdapter
SelectCommand InsertCommand UpdateCommand DeleteCommand
Source de donnes
Mise jour
Le composant DataSet reprsente une sorte de cache de donnes. Il stocke en local une partie de la base de donnes qui correspond au rsultat d'une requte de slection adresse par l'application la source de donnes. Ce rsultat est stock dans une table (DataTable) du DataSet. Il est noter que le DataSet peut comporter plusieurs tables cres chacune par une requte de slection. Le composant DataAdapter joue le rle d'intermdiaire entre la source de donnes et le DataSet. Dans ce cadre ce composant permet de : o Rcuprer le rsultat correspondant une requte de slection partir de la source de donnes et remplit avec, le DataSet. o Assurer la mise jour de la source de donnes dans le cas o les donnes locales du DataSet ont t modifies par l'utilisateur. Remarque : La copie locale des donnes stocke par un DataSet se trouve sur la machine cliente du serveur de base de donnes. Dans les applications Windows, il s'agit gnralement de la machine de l'utilisateur (cas des clients lourds). Pour les applications Web ce client est gnralement le serveur qui stocke les pages d'accs aux donnes (Serveurs Web). Les internautes travers leurs navigateurs (clients lgers) ne peuvent recevoir en effet que du HTML ou du javaScript.
Un DataAdapter possde quatre proprits de type Command qui reprsentent les actions que peut assurer l'adaptateur entre une source de donnes et un DataSet. Ces commandes sont :
93
Karim Kalti
Objet Command
SelectCommand InsertCommand UpdateCommand DeleteCommand
Signification
Contient une instruction SQL SELECT permettant de slectionner des donnes partir de la base et de les placer dans un DataSet. Contient une instruction SQL INSERT permettant d'insrer physiquement dans la base de donnes les lignes nouvellement ajoutes au DataSet. Contient une instruction SQL UPDATE permettant d'appliquer la base de donnes les modifications apportes sur les lignes du DataSet. Contient une instruction SQL DELETE permettant de supprimer physiquement de la base de donnes les lignes supprimes dans le DataSet.
L'appel de la mthode Fill du DataAdapter engendre l'excution automatique de l'objet SelectCommand. Le DataSet est alors rempli avec le rsultat de cette commande. L'appel de la mthode Update engendre l'excution des objets InsertCommand, UpdateCommand et DeleteCommand.
L'adaptateur OleDbDataAdapter
DataAdapter est un modle. Les classes rellement instanciables par les programmeurs sont celles qui implmentent ce modle. Ce paragraphe prsente l'implmentation OleDbDataAdapter propose par le fournisseur OleDb. Espace de noms : System.Data.OleDb Constructeurs : Constructeurs
OleDbDataAdapter() OleDbDataAdapter(OleDbCommand) OleDbDataAdapter( string ClauseSelect, string ChanedeConnexion ) OleDbDataAdapter( string ClauseSelect, OleDbConnection Cnn ) Cre un objet DataAdapter non initialis. Cre un objet DataAdapter partir d'un objet OleDbCommand (il s'agit d'une commande de slection. Cette commande est affecte la proprit SelectCommand de l'adaptateur). Cre un objet DataAdapter partir d'une requte de slection qui sera utilise par Fill, et d'une chane de connexion indiquant la source de donnes. Dans ce cas, il n'est pas ncessaire d'tablir la connexion l'aide d'un objet OleDbConnection. Ce dernier est automatiquement cr. Mme effet que le constructeur prcdent. Mais ici l'objet de connexion doit tre explicitement cr et pass au constructeur.
Principales proprits : Les principaux attributs sont : OleDbSelectCommand, OleDbInsertCommand, OleDbUpdateCommand, OleDbDeleteCommand.dont les interfaces viennent d'tre prsentes au paragraphe prcdent.
Signification
Remplit un DataSet pass comme argument avec le rsultat de la requte de slection passe au constructeur. Fill renvoie le nombre de lignes reues du serveur. Une table est ainsi ajoute au DataSet. La table porte par dfaut le nom "Table". Aucune table n'est cependant ajoute au DataSet si ce nombre de lignes est gal zro. Mme effet que la version prcdente mais en donnant la possibilit de spcifier explicitement un nom la table ajoute au DataSet. Si une table qui porte le mme nom existe dj dans le DataSet alors la mthode Fill remplit cette table et aucune nouvelle table n'est cre.
Comme la fonction prcdente mais en remplissant le DataSet avec NbRecords lignes partir de la ligne numro StartRecord. (Les lignes provenant du SELECT).
94
Karim Kalti
int Fill(DataTable)
Insre directement le rsultat du SELECT dans un objet table en mmoire. Engendre l'excution des commandes INSERT, UPDATE et DELETE du DataAdapter afin de rpercuter dans la source de donnes les mises jour effectues dans le DataSet. Update retourne le nombre de lignes mises jour. Dans le cas o la table de la source n'est pas trouve une exception de type SystemException est leve. Dans le cas de l'echec d'une commande (insert,) une exception de type DbConcurrencyException est leve. Engendre l'excution des commandes INSERT, UPDATE et DELETE du DataAdapter afin de rpercuter dans la source de donnes les mises jour effectues dans le DataTable. Update retourne le nombre de lignes mises jour. Dans le cas o la table de la source n'est pas trouve une exception de type SystemException est leve. Dans le cas de l'echec d'une commande (insert,) une exception de type DbConcurrencyException est leve.
L'objet DataSet
Un DataSet reprsente une copie locale d'une partie de la base de donnes. Les donnes de cette copie locale peuvent tre consultes et modifies sans avoir besoin accder au serveur de donnes.
Modle objet d'un DataSet Le modle objet d'un DataSet est donn par la figure suivante :
Un objet DataSet comporte gnralement une collection de tables (objets DataTable) et une collection de relations (objets DataRelation). Chaque table comporte une collection de colonnes (objets DataColumn), une collection de lignes (objets DataRow) et une collection de contraintes (objets Constraint). Les tables peuvent tre cres et ajoutes au DataSet d'une manire explicite ou par appel aux mthodes Fill de plusieurs adaptateurs de donnes. Chaque adaptateur de donnes s'occupe gnralement de la gestion (remplissage et mise jour) d'une table du DataSet.
95
Karim Kalti
Un objet DataSet est compltement dconnect de la source de donnes. Il est indpendant des diffrents fournisseurs de donnes (implmentation unique pour les diffrents fournisseurs OleDb, SQL Server, Oracle,). En .NET, les donnes d'un DataSet sont crites en XML et le schma est crit en XSD (XML Schema Definition Language). Un DataSet peut ainsi importer et exporter d'une manire native les donnes au format XML. Il peut galement tre utilis pour changer des donnes entre diffrentes sources de donnes. Espace de noms : System.Data Constructeurs : Constructeur
DataSet() DataSet(string)
Signification
Cre un objet DataSet. Cre un objet DataSet en lui donnant un nom.
Signification
Nom donn au DataSet non initialis. Indique si les contraintes doivent tre vrifies ou non lors des oprations de mise jour effectues dans le DataSet. (true signifie qu'il y a vrification, c'est la valeur par dfaut pour cette proprit). Collection de relations (objets de type DataRelation) Collection de tables (objets de type DataTable)
Signification
Efface le contenu du DataSet en supprimant toutes les lignes des tables. Copie la structure du DataSet (tables, relations, contraintes) sans copier les donnes. Copie la fois la structure et les donnes du DataSet. Retourne la reprsentation XML des donnes stockes dans le DataSet. Retourne le schma XSD de la reprsentation des donnes du DataSet. Fusionne le DataSet pass en argument et son schma avec le DataSet courant. Fusionne la table passe en argument et son schma dans le DataSet courant.
Exemple 1 : On considre la base de donnes Biblio comportant la table Ouvrage donne comme suit : Ouvrage Champ Type Inventaire Entier Titre Chane Anne ddition Entier
96
Karim Kalti
L'exemple suivant montre la cration d'un DataSet qui rcupre en local la liste des ouvrages de la base Biblio. Cette liste est place dans un objet DataTable nomm Ouvrage.
// Cration de la chane de connexion string StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\Data\Biblio.mdb"; // Cration de l'objet de connexion OleDbConnection Cnn = new OleDbConnection(StrCnn); // Ouverture de la connexion Cnn.Open(); // Texte de la requte qui sera stock dans la proprit SelectCommand de l'adaptateur string StrSelect = "SELECT * FROM Ouvrage"; // Cration de l'adaptateur de donnes OleDbDataAdapter DA = new OleDbDataAdapter(StrSelect,Cnn); // Cration du DataSet DataSet DS = new DataSet(); // Remplissage du DataSet DA.Fill(DS, "Ouvrage");
L'objet DataTable
L'objet DataTable est une reprsentation en mmoire locale (ct client) d'une table de base de donnes. Une table dans un DataSet comporte un schma et des donnes. Le schma est dfini par les colonnes de la table (collection d'objets de type DataColumn) et par les contraintes appliques aux colonnes. Ces contraintes concernent la spcification de la cl primaire (objet UniqueConstraint) et de la cl trangre (objet ForeignKeyConstraint). Les donnes d'une table sont stockes dans des lignes (collection d'objets de type DataRow). Espace de noms : System.Data Constructeurs :
DataTable() DataTable(string) Cre une table sans lui donner de nom. Cre une table en lui donnant un nom.
Type
string DataSet DataRelationCollection DataRelationCollection DataColumnsCollection DataRowCollection Constraintcollection DataColumn[]
Signification
Nom donn la table. En lecture seule, cette proprit permet de rcuprer le DataSet auquel appartient la table. En lecture seule. Cette proprit donne la collection de relations (objets DataRelation) de type enfant de la table. En lecture seule. Cette proprit donne la collection de relations (objets DataRelation) de type parent de la table. En lecture seule. Cette proprit donne la collection de colonnes (objets de type DataColumn) de la table. En lecture seule. Cette proprit donne la collection des lignes (objets de type DataRow) de la table. En lecture seule. Cette proprit donne la collection des contraintes associes la table. En lecture et criture. Cette proprit contient la liste des colonnes qui composent la cl primaire de la table.
Signification
Efface le contenu d'une table (les lignes). Clone la structure d'une table (schma et contraintes). Copie la fois la structure et les donnes d'une table. Ajoute la ligne dr la table. Crer une nouvelle ligne ayant le mme schma que la table.
97
Karim Kalti
L'objet DataTableCollection
Cet objet reprsente une collection de tables (DataTable). Principales proprits : Nom Type
Count Item int DataTable
Signification
Retourne le nombre de tables dans la collection. C'est un indexeur qui permet d'accder une table particulire de la collection. La table peut tre indexe par un numro (ordre d'ajout de la table dans la collection) ou par son nom.
Signification
Ajoute une nouvelle table la collection. La table possde comme nom la chane passe en argument. La mthode retourne une rfrence sur la table ajoute. Ajoute la table passe en argument la collection. Ajoute un tableau de tables la collection. ( la fin de la collection) Supprime toutes les tables de la collection. Vrifie si la collection contient la table dont le nom est pass en argument. Renvoi la position de l'indexe (position ordinale dans la collection) de la table qui est passe ou dont le nom est pass en argument. Supprime de la collection la table qui est passe ou dont le nom est pass en argument. Supprime de la collection la table dont l'indexe est pass en argument.
Exemple 1 : Cet exemple montre les diffrentes possibilits d'accs la table Ouvrage du DataSet DS cr dans l'exemple prcdent.
DS.Tables[0];
Accs l'aide de l'indice de la table dans le DataSet. (Les indices commencent partir de 0. Ils sont affects aux tables suivant l'ordre d'ajout de ces dernires au DataSet.
DS.Tables["Ouvrage"];
Accs l'aide d'un indexeur de la collection Tables qui prend un indice de type chane. Cet indice reprsente le nom de la table accder. Exemple 2: Il est possible de compter le nombre de tables du DataSet et ce l'aide de la proprit Count de la collection Tables du DataSet.
int n = DS.Tables.Count;
Remarque : Les objets DataColumnCollection et DataRowCollection possdent les mmes caractristiques que DataTableCollection. (Ce sont toutes des collections). On trouve ainsi presque les mmes proprits et mthodes mais c'est seulement le type de l'objet manipul par la collection qui change (respectivement DataColumn et DataRow au lieu de DataTable).
L'objet DataColumn
L'objet DataColumn reprsente une colonne d'une table en mmoire. Espace de noms : System.Data Constructeurs :
DataColumn() DataColumn(string N) DataColumn(string N, Type T) Cre une colonne sans lui donner de nom. Cre une colonne tout en lui attribuant un nom. Cre une colonne tout en lui attribuant un nom et un type. Type est une classe du .NET de l'espace de noms System qui permet de stocker des types de donnes.
98
Karim Kalti
Signification
Indique si des valeurs nulles peuvent tre introduites dans la colonne. Indique si le contenu de cette colonne doit tre automatiquement incrment lors de chaque ajout. Valeur de dbut d'un champ autoincrment. Valeur d'incrmentation (par dfaut 1). Libell de la colonne. Si ce champ n'est pas explicitement spcifi alors il prend par dfaut la valeur de ColumnName. Nom du champ correspondant la colonne. Type du champ. Valeur par dfaut lors d'un ajout Position de la colonne dans la collection des colonnes de la table. Indique si le contenu de la colonne est en lecture seule. Indique si la valeur de chaque ligne de la colonne doit tre unique.
Les quelques mthodes publiques de DataColumn sont rarement utilises. Exemple 1 : L'accs une colonne d'une table peut se faire de diffrentes manires comme le montrent les quatre instructions quivalentes suivantes :
DS.Tables["Ouvrage"].Columns[0]; DS.Tables["Ouvrage"].Columns["Inventaire"]; DS.Tables[0].Columns[0]; DS.Tables[0].Columns["Inventaire"];
L'objet DataRow
L'objet DataRow reprsente une ligne d'une table. Espace de noms : System.Data Constructeurs : Pas de constructeurs explicites (constructeur par dfaut seulement). Gnralement c'est la mthode NewRow de la classe DataTable qui est utilise pour construire un DataRow. Principales proprits : Nom
Item ItemArray RowState Table
Type
Indexeur de la forme Object this[ ] object[] enum DataRowState DataTable
Signification
Indexeur donnant accs au contenu de chaque colonne de la ligne. Dans les crochets de l'indexeur il est possible de spcifier le numro de colonne, le nom de la colonne ou encore un objet DataColumn. Tableau des contenus des diffrentes colonnes de la ligne (contenu de la ligne). Etat de la ligne. RowState peut prendre l'une des valeurs suivantes de l'numration DataRowState : (Detached, Unchanged, Added, Deleted, Modified). Table laquelle appartient la ligne.
99
Karim Kalti
L'tat d'une ligne L'tat d'une ligne est dtermin par la proprit RowState de la classe DataRow. Les valeurs possibles de cette proprit sont celles de l'numration DataRowState : Valeur de DataRowState
Unchanged Added Modified Deleted
Signification
Aucune modification n'a t effectue sur la ligne depuis l'appel AcceptChanges ou depuis la cration de la ligne l'aide de la mthode Fill du DataAdapter. La ligne a t ajoute la table mais la mthode AcceptChanges n'a pas t appele. Certains lments de la ligne ont t modifis. La ligne a t supprime de la table et AcceptChanges n'a pas t encore appele. Cette valeur signifie que la ligne a t cre mais qu'elle ne fait pas partie d'un DataRowCollection. Le RowState d'une ligne cre prend la valeur Detached. Une fois la ligne ajoute un DataRowCollection l'aide de la mthode Add, la proprit RowState prend la valeur Added. La valeur Detached est galement dfinie pour une ligne qui a t supprime d'un DataRowCollection l'aide de la mthode Remove ou par la mthode Delete suivie de l'appel la mthode AcceptChanges.
Detached
Le DataAdapter se base sur la proprit RowState pour dcider de la commande excuter pour chaque ligne lors de l'appel de la mthode Update : (InsertCommand pour Added, UpdateCommand pour Modified et DeleteCommand pour Deleted). La version d'une ligne La version d'une ligne peut prendre l'une des valeurs de l'numration DataRowVersion. DataRowVersion
Current Default Original Proposed
Signification
C'est la version qui contient les valeurs actuelles de la ligne. Cette version de ligne n'existe pas pour les lignes dont le RowState est Deleted. C'est la version par dfaut d'une ligne particulire. La version par dfaut d'une ligne Added, Modified ou Unchanged est Current. La version par dfaut d'une ligne Deleted est Original. La version par dfaut d'une ligne Detached est Proposed. C'est la version qui contient les valeurs d'origine de la ligne. Cette version de ligne n'existe pas pour les lignes ayant un RowState Added. C'est la version qui contient les valeurs proposes d'une ligne. Cette version existe pendant une opration de modification sur une ligne ou pour une ligne qui ne fait pas partie d'un DataRowCollection.
Il est possible de savoir si une version particulire d'une ligne existe et ce en utilisant la mthode HasVersion. Les versions des lignes sont essentiellement utilises durant les oprations de mise jour de donnes partir du DataSet vers la base de donnes.
Signification
La mthode AcceptChanges permet de valider tous les changements effectus sur une ligne depuis le dernier appel AcceptChanges. Si le RowState d'une ligne est Added ou Modified alors il devient Unchanged. Si le RowState d'une ligne est Deleted alors la ligne sera supprime de la table et son tat devient Detached. Retourne une valeur indiquant si la version passe en argument existe pour la ligne courante.
bool HasVersion(DataRowVersion)
Sur le plan pratique l'appel explicite de AcceptChanges est rare. Cet appel est souvent implicite. Il est effectu surtout par la mthode Update du DataAdapter. Ceci permet de ne faire que la mise jour des nouvelles modifications si un autre appel Update est effectu. L'appel implicite de AcceptChanges aprs l'appel de la mthode Fill du DataAdapter est dtermin quant lui par la proprit AcceptChangesDuringFill de la classe DataAdapter (la valeur par dfaut est true. Elle signifie qu'il y a appel). La mthode AcceptChanges est membre non seulement de la classe DataRow mais galement des classes DataSet et DataTable. o Pour DataRow son effet touche la ligne. o Pour DataTable son effet touche toutes les lignes d'une table. o Pour DataSet son effet touche toutes les lignes de toutes les tables du DataSet.
100
Karim Kalti
Exemple 1 : Accs une ligne L'accs la nime ligne d'une table se fait comme suit :
DS.Tables["Ouvrage"].Rows[n-1];
Les indices commencent toujours partir de 0. Si la n ime ligne n'existe pas alors une exception sera leve. L'accs au mime champ de la nime ligne se fait comme suit :
// Accs l'aide des indices DS.Tables["Ouvrage"].Rows[n-1][m-1]; // Accs travers le nom du champ. DS.Tables["Ouvrage"].Rows[n-1]["Inventaire"];
chane de connexion // Objet de Connexion Texte de la commande Select du DataAdapter // Adaptateur de donnes
public DisconnectedMode(string strcnn) { StrCnn =strcnn; Cnn = new OleDbConnection(StrCnn); Cnn.Open(); StrSelect = "SELECT * FROM Ouvrage"; DA = new OleDbDataAdapter(StrSelect,Cnn); DS = new DataSet(); // Remplissage du DataSet DA.Fill(DS, "Ouvrage"); } public void Disconnect() { //Fermeture de la connexion Cnn.Close(); } public void ShowStructure() { // Dtermination dynamique du nombre des tables et de leurs noms Console.WriteLine("Nombre de tables du DataSet : "+DS.Tables.Count); for(int i=0;i<DS.Tables.Count;i++) Console.WriteLine(DS.Tables[i].TableName+" ("+i+")"); // Dtermination dynamique des structures des tables Console.WriteLine("\n/////// Structures des tables du DataSet ///////\n");
101
Karim Kalti
foreach(DataColumn dc in dt.Columns) Console.WriteLine(dc.ColumnName+" ("+dc.DataType.Name+")"); } } public void ShowContent() { foreach(DataRow rw in DS.Tables["Ouvrage"].Rows) { Console.WriteLine("************************************"); Console.WriteLine("Inventaire : "+rw["Inventaire"]); Console.WriteLine("Titre : "+rw["Titre"]); Console.WriteLine("Anne d'dition : "+rw["Anne d'dition"]); } } } class Prog { public static void Main() { DisconnectedMode ins = new DisconnectedMode("C:\\Data\\Biblio.mdb"); ins.ShowStructure(); ins.ShowContent(); ins.Disconnect(); } }
L'objet CommandBuilder
L'objet CommandBuilder est utilis pour gnrer d'une manire automatique les objets DeleteCommand, InsertCommand et UpdateCommand du DataAdapter ncessaires pour effectuer la mise jour des donnes partir du DataSet. L'objet CommandBuilder se base sur le texte de l'objet SelectCommand du DataAdapter pour dduire les informations ncessaires cette gnration comme le nom de la table, la liste des champs rcuprs, les contraintes, etc. L'objet CommandBuilder est essentiellement utilis pour gnrer des commandes relatives des tables simples. (Gnralement pour les tables du DataSet issues d'une seule table de la source de donnes. Le CommandBuilder ne convient pas aux tables simples cres par un SELECT qui ne retourne pas parmi la liste des champs le champ cl. Il ne convient pas galement aux tables qui rsultent d'une opration de jointure). L'objet CommandBuilder est dpendant du fournisseur de donnes. L'implmentation propose par le fournisseur OleDb est OleDbCommandBuilder.
Signification
Obtient ou dfinit un objet OleDbDataAdapter pour lequel les instructions SQL sont automatiquement gnres. Obtient ou dfinit le ou les caractres de dbut utiliser lors de la spcification d'objets de base de donnes (par exemple, des tables ou colonnes) dont les noms contiennent des caractres tels que des espaces ou des jetons rservs. Obtient ou dfinit le ou les caractres de fin utiliser lors de la spcification d'objets de base de donnes (par exemple, des tables ou colonnes) dont les noms contiennent des caractres tels que des espaces ou des jetons rservs.
QuoteSuffix
string
102
Karim Kalti
Signification
Actualise les informations de schma de la base de donnes utilises pour gnrer des instructions INSERT, UPDATE ou DELETE. Cette mthode doit tre appele si l'adaptateur de donnes change sa commande SELECT aprs la construction du CommandBuilder. Cet appel va engendrer alors l'actualisation des informations de schma du CommandBuilder et la construction de commandes valides. Obtient l'objet OleDbCommand gnr automatiquement et requis pour effectuer des suppressions au niveau de la source de donnes. Obtient l'objet OleDbCommand gnr automatiquement et requis pour effectuer des insertions au niveau de la source de donnes. Obtient l'objet OleDbCommand gnr automatiquement et requis pour effectuer des mises jour au niveau de la source de donnes.
Exemple : Mise jour des donnes l'aide d'un DataAdapter Cet exemple montre la mise jour des modifications apportes aux donnes de la table Ouvrage situe dans le DataSet vers la table qui lui correspond dans la source de donnes. Le tableau suivant donne l'tat de la table Ouvrage avant la mise jour des donnes :
Ouvrage Inventaire Titre Anne d'dition 1 Programmation C 1996 2 Les rseaux 2004 3 Internet 2000 4 Les bases de donnes 1998
103
Karim Kalti
using System; using System.Data; using System.Data.OleDb; class DisconnectedMode { private string StrCnn; // La chane de connexion private OleDbConnection Cnn; // Objet de Connexion private string StrSelect; // Texte de la commande Select du DataAdapter private OleDbDataAdapter DA; // Adaptateur de donnes private DataSet DS; private OleDbCommand DelCmd; private OleDbCommand InsCmd; private OleDbCommand UpdateCmd; public DisconnectedMode() {StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\Data\Biblio.mdb"; Cnn = new OleDbConnection(StrCnn); Cnn.Open(); StrSelect = "SELECT * FROM Ouvrage"; DA = new OleDbDataAdapter(StrSelect,Cnn); DS = new DataSet(); // Remplissage du DataSet DA.Fill(DS, "Ouvrage"); } public void Disconnecte() { Cnn.Close();} public void ShowContent() { foreach(DataRow rw in DS.Tables["Ouvrage"].Rows) { Console.WriteLine("************************************"); Console.WriteLine("Inventaire : "+rw["Inventaire"]); Console.WriteLine("Titre : "+rw["Titre"]); Console.WriteLine("Anne d'dition : "+rw["Anne d'dition"]); } } public void UpdateDataSet() { // Code d'ajout d'une ligne par programmation DataRow dr = DS.Tables["Ouvrage"].NewRow(); dr["Inventaire"]=5; dr["Titre"]= "UML"; dr["Anne d'dition"]=2004; DS.Tables["Ouvrage"].Rows.Add(dr); // Code de Modification d'une ligne DS.Tables["Ouvrage"].Rows[0]["Titre"]="Programmation C++"; DS.Tables["Ouvrage"].Rows[0]["Anne d'dition"]=2003; // Code de suppression d'une ligne DS.Tables["Ouvrage"].Rows[2].Delete(); } public void UpdateDataSource() { // Cration de la commande de suppression string StrDelete = "DELETE FROM Ouvrage WHERE Inventaire = ?"; DelCmd = new OleDbCommand(StrDelete, Cnn); OleDbParameter Param = new OleDbParameter(); Param.ParameterName="OriginInventaire"; Param.OleDbType = OleDbType.Integer; Param.Direction = ParameterDirection.Input; Param.IsNullable = false; Param.SourceColumn="Inventaire"; Param.SourceVersion=DataRowVersion.Original; DelCmd.Parameters.Add(Param); // Cration de la commande d'insertion string StrInsert = "INSERT INTO Ouvrage VALUES (?,?,?)"; InsCmd = new OleDbCommand(StrInsert, Cnn); OleDbParameter ParamInventaire = new OleDbParameter("ParInv",OleDbType.Integer,0, ParameterDirection.Input,false,(byte)0,(byte)0,"Inventaire",DataRowVersion.Current,null); OleDbParameter ParamTitre = new OleDbParameter("ParTitre",OleDbType.VarWChar,50, ParameterDirection.Input,false,(byte)0,(byte)0,"Titre",DataRowVersion.Current,null);
104
Karim Kalti
OleDbParameter ParamEdition = new OleDbParameter("ParEdition",OleDbType.Integer,0, ParameterDirection.Input,false,(byte)0,(byte)0,"Anne d'dition",DataRowVersion.Current, null); InsCmd.Parameters.Add(ParamInventaire); InsCmd.Parameters.Add(ParamTitre); InsCmd.Parameters.Add(ParamEdition); // Cration de la commande de modification string StrUpdate = "Update Ouvrage SET Inventaire=?, Titre=?, [Anne d'dition]=? WHERE Inventaire=? AND (Titre = ?) AND ([Anne d'dition]= ? OR ? IS NULL AND [Anne d'dition] IS NULL)"; UpdateCmd = new OleDbCommand(StrUpdate, Cnn); UpdateCmd.Parameters.Add(new OleDbParameter("NouvInventaire",OleDbType.Integer,0, "Inventaire")); UpdateCmd.Parameters.Add(new OleDbParameter("NouvTitre", OleDbType.VarWChar,50,"Titre")); UpdateCmd.Parameters.Add(new OleDbParameter("NouvEdition", OleDbType.Integer,0,"Anne d'dition")); UpdateCmd.Parameters.Add(new OleDbParameter("OriginalInv", OleDbType.Integer,0, ParameterDirection.Input,false,(byte)0,(byte)0,"Inventaire",DataRowVersion.Original, null)); UpdateCmd.Parameters.Add(new OleDbParameter("OriginalTitre", OleDbType.VarWChar,50, ParameterDirection.Input, false,(byte)0,(byte)0,"Titre",DataRowVersion.Original,null)); UpdateCmd.Parameters.Add(new OleDbParameter("OriginalEdition1", OleDbType.Integer,0, ParameterDirection.Input,false,(byte)0,(byte)0,"Anne d'dition",DataRowVersion.Original, null)); UpdateCmd.Parameters.Add(new OleDbParameter("OriginalEdition2", OleDbType.Integer,0, ParameterDirection.Input,false,(byte)0,(byte)0,"Anne d'dition",DataRowVersion.Original, null)); // Ajout des commandes l'adaptateur DA.DeleteCommand=DelCmd; DA.InsertCommand=InsCmd; DA.UpdateCommand=UpdateCmd; DA.Update(DS.Tables["Ouvrage"]); } } class Prog { public static void Main() { DisconnectedMode ins = new DisconnectedMode(); ins.UpdateDataSet(); ins.UpdateDataSource(); ins.ShowContent(); } }
Quelques prcisions : Il n'est pas ncessaire de dfinir la prcision pour les types numriques qui ne sont pas du type OleDbType.Decimal. Si la version d'une ligne n'est pas explicitement dfinie alors elle prend par dfaut la valeur Current. Dans le mode dconnect, la proprit Value d'un paramtre d'un objet commande d'un DataAdapter est dtermine d'une manire automatique en se basant sur les proprits SourceVersion et SourceColumn. Commentaire sur la commande de suppression : A chaque fois que le DataAdapter trouve une ligne dont l'tat est Deleted, il excute la commande DeleteCommand du DataAdapter. Cette commande rcupre la valeur originale de la ligne pour valoriser le paramtre de la requte qu'elle encapsule puis supprime physiquement cette ligne partir de la source de donnes. (Il est noter qu'une ligne supprime dans le DataSet ne possde pas de version courrante).
105
Karim Kalti
Commentaire sur la commande d'insertion : A chaque fois que le DataAdapter trouve une ligne dont l'tat est Added, il excute la commande InsertCommand du DataAdapter. Cette commande rcupre la version courante (la version par dfaut) de la ligne dans le DataSet et ce pour valoriser les paramtres de la requte puis insre physiquement cette ligne dans la source de donnes. Commentaire sur la commande de modification : A chaque fois que le DataAdapter trouve une ligne dont l'tat est Modified, il excute la commande UpdateCommand du DataAdapter. Cette commande rcupre la valeur courante (version par dfaut) de la ligne pour valoriser la premire partie des paramtres de la requte (les paramtres avant le WHERE). Les conditions introduites par le WHERE permettent de vrifier si la ligne n'a pas t modifie dans la source de donnes (par un autre utilisateur) depuis son chargement en local dans le DataSet (car dans le mode dconnect de tels changements ne peuvent pas tre immdiatement visibles dans le DataSet). Les paramtres utiliss par ces conditions prennent leurs valeurs de la version originale de la ligne (avant modification) et non de la version courante comme c'est le cas des paramtres de la premire partie de la requte. L'expression Champ=NULL est toujours fausse (en BD, NULL n'est pas une valeur mais signifie que le champ n'a pas de valeur). Ainsi chaque fois qu'un champ peut tre NULL, le critre doit tre de la forme Champ = ? OR ? IS NULL AND Champ IS NULL ce qui veut dire que le champ est gal au paramtre ou le champ et le paramtre sont tous les deux NULL. Cette condition est obligatoire pour les champs qui peuvent accepter la valeur NULL (IsNullable = true). La gnration l'aide de l'objet CommandBuilder Le code de mise jour des donnes en utilisant un objet CommandBuilder est assez simple. Il se prsente comme suit :
string StrCnn = @"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\Data\Biblio.mdb"; OleDbConnection Cnn = new OleDbConnection(StrCnn); Cnn.Open(); string StrSelect = "SELECT * FROM Ouvrage"; OleDbDataAdapter DA = new OleDbDataAdapter(StrSelect,Cnn); OleDbCommandBuilder CB = new OleDbCommandBuilder(DA); CB.QuotePrefix = "["; CB.QuoteSuffix = "]"; DataSet DS = new DataSet(); DA.Fill(DS, "Ouvrage"); // Mettre ici le code de modification des donnes du DataSet. // Mise jour des donnes vers la source DA.Update(DS,"Ouvrage"); Cnn.Close();
L'objet DataRelation
Cette classe reprsente une relation Parent/Enfant entre deux tables du DataSet. Espace de noms : System.Data.DataRelation Quelques constructeurs :
DataRelation( string N, DataColumn P, DataColumn C) DataRelation( string N, DataColumn[] P, DataColumn[] C) Cre une nouvelle relation qui possde comme nom interne N, comme champ parent P et comme champ enfant C.
Cre une nouvelle relation qui possde comme nom interne N, comme champs parents P et comme champs enfants C.
106
Karim Kalti
Type
String DataColumn[] DataColumn[] DataTable DataTable DataSet
Signification
Nom de la relation. En lecture seule. Stocke la liste des colonnes "enfants" de la relation. En lecture seule. Stocke la liste des colonnes "parents" de la relation. En lecture seule. Indique la table contenant le (les) champ(s) "enfant(s)" de la relation. En lecture seule. Indique la table contenant le (les) champ(s) "parent(s)" de la relation. En lecture seule. Indique le DataSet auquel appartient la relation.
Exemple : Ajout d'une relation entre Ouvrage et Prt On considre les trois tables suivantes : Ouvrage Champ Type Champ Type Champ Type Inventaire Entier Id Entier Numro Entier Titre Chane Nom Chane Inventaire Chane IdLecteur Entier Date Date Anne ddition Entier
Lecteur
Prt
L'exemple suivant montre l'ajout d'une relation entre les deux tables Ouvrage et Prt.
DataColumn ParentCol; DataColumn ChildCol; ParentCol = DS.Tables["Ouvrage"].Columns["Inventaire"]; ChildCol = DS.Tables["Prt"].Columns["Inventaire"]; DataRelation RelOuvragePret = new DataRelation("InventaireRelation", ParentCol, ChildCol); DS.Relations.Add(RelOuvragePret);
107
Karim Kalti
Type
string DataTable Collection Bool
Signification
Nom de la contrainte (lecture seule) Nom de la table laquelle est associe la contrainte. Liste des colonnes concernes par la contrainte. Indique si la contrainte est une cl primaire. (true si c'est une contrainte de cl, c'est la valeur par dfaut).
// Try to add an identical row. try{ myRow = myTable.NewRow(); myRow["id"] = 1; myRow["Name"] = "John"; myTable.Rows.Add(myRow); } catch(Exception e) { System.Diagnostics.EventLog log = new System.Diagnostics.EventLog(); log.Source = "My Application"; log.WriteEntry(e.ToString()); Console.WriteLine("Exception of type {0} occurred.", e.GetType()); } } private void AddUniqueConstraint (DataTable myTable){ // Create the DataColumn array. DataColumn[] myColumns = new DataColumn[2]; myColumns[0] = myTable.Columns["id"]; myColumns[1] = myTable.Columns["Name"]; UniqueConstraint myUniqueConstraint; myUniqueConstraint = new UniqueConstraint("idNameConstraint", myColumns); myTable.Constraints.Add(myUniqueConstraint); }
La classe ForeignKeyConstraint Cette contrainte permet de spcifier comment agir lorsqu'une donne dpendante de deux ou plusieurs tables diffrentes est supprime. Faut-il la supprimer dans les autres tables, la mettre null ou mettre une valeur par dfaut. Quelques constructeurs :
public ForeignKeyConstraint(string N, DataColumn Parent, DataColumn Child); public ForeignKeyConstraint(string N, DataColumn[] Parent, DataColumn[] Child); Cre une contrainte nomme N entre deux colonnes Parent et Enfant. Cre une contrainte nomme N entre un ensemble de colonnes Parents et un ensemble de colonnes Enfants.
108
Karim Kalti
Signification
Nom de la contrainte (lecture seule) Nom de la table "enfant" associe la contrainte. Liste des colonnes enfants de la contrainte. Nom de la table "Parent" de la contrainte. Liste des colonnes "Parent" de la contrainte. Permet de spcifier comment agir sur les donnes dpendantes lorsqu'une ligne est supprime. Les actions possibles sont donnes par l'numration Rule Permet de spcifier comment agir sur les donnes dpendantes lorsqu'une ligne est mise jour. Les actions possibles sont donnes par l'numration Rule
Signification
Supprime ou met jour les lignes relies la ligne supprime ou modifie. C'est la valeur par dfaut pour les proprit DeleteRule et UpdateRule. Aucune action n'est effectue sur les lignes relies. Met les valeurs des colonnes des lignes relies la valeur spcifie dans la proprit DefaultValue de l'objet DataColumn. Met les valeurs dans les lignes relies la valeur DBNull.
109
Karim Kalti
Annexe A
Code gnr par VS.NET 2003 suite la cration l'aide de l'assistant d'un Adaptateur de donnes et d'un DataSet
la partie attritbuts System.Data.OleDb.OleDbDataAdapter oleDbDataAdapter1; System.Data.OleDb.OleDbCommand oleDbSelectCommand1; System.Data.OleDb.OleDbCommand oleDbInsertCommand1; System.Data.OleDb.OleDbCommand oleDbUpdateCommand1; System.Data.OleDb.OleDbCommand oleDbDeleteCommand1; System.Data.OleDb.OleDbConnection oleDbConnection1; System.Data.DataSet dataSet1;
-----------------------------------------------------------------
// Dans la mthode InitializeComponents this.oleDbDataAdapter1 = new System.Data.OleDb.OleDbDataAdapter(); this.oleDbDeleteCommand1 = new System.Data.OleDb.OleDbCommand(); this.oleDbConnection1 = new System.Data.OleDb.OleDbConnection(); this.oleDbInsertCommand1 = new System.Data.OleDb.OleDbCommand(); this.oleDbSelectCommand1 = new System.Data.OleDb.OleDbCommand(); this.oleDbUpdateCommand1 = new System.Data.OleDb.OleDbCommand(); this.dataSet1 = new System.Data.DataSet(); ((System.ComponentModel.ISupportInitialize)(this.dataSet1)).BeginInit(); // oleDbDataAdapter1 this.oleDbDataAdapter1.DeleteCommand = this.oleDbDeleteCommand1; this.oleDbDataAdapter1.InsertCommand = this.oleDbInsertCommand1; this.oleDbDataAdapter1.SelectCommand = this.oleDbSelectCommand1; // Le Mapping est utilis pour faire la correspondance entre les noms utiliss par le DataSet et ceux utiliss par // la source de donnes. Il peut tre exploit pour modifier les noms au niveau du DataSet. this.oleDbDataAdapter1.TableMappings.AddRange(new System.Data.Common.DataTableMapping[] { new System.Data.Common.DataTableMapping("Table","Ouvrage",new System.Data.Common.DataColumnMapping[]{ new System.Data.Common.DataColumnMapping("Anne d\'dition", "Anne d\'dition"), new System.Data.Common.DataColumnMapping("Inventaire", "Inventaire"), new System.Data.Common.DataColumnMapping("Titre", "Titre")})}); this.oleDbDataAdapter1.UpdateCommand = this.oleDbUpdateCommand1; // oleDbDeleteCommand1 this.oleDbDeleteCommand1.CommandText = "DELETE FROM Ouvrage WHERE (Inventaire = ?) AND ([Anne d\'dition] = ? OR ? IS NUL" +"L AND [Anne d\'dition] IS NULL) AND (Titre = ?)"; this.oleDbDeleteCommand1.Connection = this.oleDbConnection1; this.oleDbDeleteCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Inventaire", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Inventaire", System.Data.DataRowVersion.Original, null)); this.oleDbDeleteCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Anne_d\'dition", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Anne d\'dition", System.Data.DataRowVersion.Original, null)); this.oleDbDeleteCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Anne_d\'dition1", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input,
false,
110
Karim Kalti
"Anne
d\'dition",
this.oleDbDeleteCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Titre", System.Data.OleDb.OleDbType.VarWChar, 50, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Titre", System.Data.DataRowVersion.Original, null)); // oleDbConnection1 this.oleDbConnection1.ConnectionString = @"Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Registry Path=;Jet OLEDB:Database Locking Mode=1;Data Source=""C:\Data\Biblio.mdb""; Jet OLEDB:Engine Type=5;Provider=""Microsoft.Jet.OLEDB.4.0"";Jet OLEDB:System database=;Jet OLEDB:SFP=False;persist security info=False;Extended Properties=;Mode=Share Deny None;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Create System Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;User ID=Admin;Jet OLEDB:Global Bulk Transactions=1"; // oleDbInsertCommand1 this.oleDbInsertCommand1.CommandText = "INSERT INTO Ouvrage([Anne d\'dition], Inventaire, Titre) VALUES (?, ?, ?)"; this.oleDbInsertCommand1.Connection = this.oleDbConnection1; this.oleDbInsertCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Anne_d\'dition", System.Data.OleDb.OleDbType.Integer, 0, "Anne d\'dition")); this.oleDbInsertCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Inventaire", System.Data.OleDb.OleDbType.Integer, 0, "Inventaire")); this.oleDbInsertCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Titre", System.Data.OleDb.OleDbType.VarWChar, 50, "Titre"));
Inventaire,
Titre
FROM
// oleDbUpdateCommand1 this.oleDbUpdateCommand1.CommandText = "UPDATE Ouvrage SET [Anne d\'dition] = ?, Inventaire = ?, Titre = ? WHERE (Inventaire = ?) AND ([Anne d\'dition] = ? OR ? IS NULL AND [Anne d\'dition] IS NULL) AND (Titre = ?)"; this.oleDbUpdateCommand1.Connection = this.oleDbConnection1; this.oleDbUpdateCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Anne_d\'dition", System.Data.OleDb.OleDbType.Integer, "Anne d\'dition"));
0,
this.oleDbUpdateCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Inventaire", System.Data.OleDb.OleDbType.Integer, 0, "Inventaire")); this.oleDbUpdateCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Titre", System.Data.OleDb.OleDbType.VarWChar, 50, "Titre")); this.oleDbUpdateCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Inventaire", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Inventaire", System.Data.DataRowVersion.Original, null)); this.oleDbUpdateCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Anne_d\'dition", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Anne d\'dition", System.Data.DataRowVersion.Original, null)); this.oleDbUpdateCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Anne_d\'dition1", System.Data.OleDb.OleDbType.Integer, 0, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Anne d\'dition", System.Data.DataRowVersion.Original, null)); this.oleDbUpdateCommand1.Parameters.Add(new System.Data.OleDb.OleDbParameter("Original_Titre", System.Data.OleDb.OleDbType.VarWChar, 50, System.Data.ParameterDirection.Input, false, ((System.Byte)(0)), ((System.Byte)(0)), "Titre", System.Data.DataRowVersion.Original, null)); // dataSet1 this.dataSet1.DataSetName = "NewDataSet"; this.dataSet1.Locale = new System.Globalization.CultureInfo("fr-FR"); ((System.ComponentModel.ISupportInitialize)(this.dataSet1)).EndInit();
111
Karim Kalti
Protocole http://
Chemin /cours/index.htm
80
Serveur Web : Un serveur Web est un logiciel qui joue le rle d'intermdiaire (middleware) entre un client (navigateur) et une page Web demande par ce client et situe sur l'ordinateur serveur. Un serveur Web reoit la requte http (url) mise par le client, l'analyse, trouve la page correspondante sur le serveur et la renvoie toujours l'aide du protocole http au client. Le serveur reoit les requtes des clients sur un port de communication. La valeur par dfaut de ce port est 80. Les principaux serveurs Web sur le march sont entre autres : Apache, Microsoft IIS (Internet Information Server), Microsoft PWS (Personal Web Server), Navigateur : Un navigateur est un logiciel qui permet de : Envoyer des requtes http sous forme d'URL un serveur qui hberge des sites Web. Rcuprer la rponse du serveur Web et l'afficher l'cran.
112
Karim Kalti
Protocole http : HTTP est un protocole qui permet d'assurer le transfert de fichiers (essentiellement au format HTML), localiss grce une chane de caractres appele URL, entre un navigateur (le client) et un serveur Web.
Logiciels ncessaires sur chaque machine Client : Navigateur Web. Serveur : Serveur Web (middleware) + les pages qui composent l'application Web.
On considre ici une application Web simple, c'est--dire une application dont les pages sont codes en HTML seulement sans aucun autre langage de script supplmentaire. 1- Le navigateur (client) demande une page Web en envoyant son URL au serveur l'aide du protocole HTTP. 2- Le serveur Web intercepte la requte du client et recherche la page demande. 3- Le serveur renvoie le code source (HTML) de la page au client l'aide du protocole HTTP. 4- Le navigateur du client reoit la rponse du serveur, interprte le code HTML reu et affiche la page qui rsulte de cette interprtation. Cette description montre le rle important qu'assure le navigateur dans ce processus d'change savoir le rle d'interprteur de code HTML.
113
Karim Kalti
114
Karim Kalti
Echanges entre client et serveur pour une page qui contient un script client
Support des langages de script par les navigateurs JavaScript Toutes les dernires versions des navigateurs (IE, Netscape Navigator, firefox,) VbScript IE seulement : Les scripts VB sont tout simplement ignors par les autres navigateurs (Pas d'erreur signale).
Remarque : Il existe d'autres langages qui permettent d'crire des modules qui sont tlchargs avec les pages Web et excuts par les machines clientes comme par exemple les applettes Java et les contrles ActiveX (C++, VB,).
Gnration ct serveur
Motivations Les scripts ct serveur peuvent tre utiliss pour effectuer tout genre d'oprations d'interaction ou de cration de contenu dynamique mais ct serveur (traitement des formulaires, mise en page dynamique, accs aux donnes, etc.). L'utilisation la plus frquente reste celle de l'accs aux donnes (gnration dynamique du contenu en se basant sur des donnes qui rsultent de l'interrogation d'une base de donnes). Ce genre d'oprations ne peut pas tre effectu ct client (ncessit dans ce cas d'avoir une copie locale de la base sur chaque client). Intgration de script serveur dans une page Web Un script serveur est gnralement insr dans le code HTML avec des balises spciales (balises qui dpendent du langage de script utilis). Une page qui contient du HTML et un script serveur ne peut pas avoir l'extension HTML ou HTM. Son extension dpend du langage du script serveur qu'elle utilise. Une mme page Web ne peut utiliser qu'un seul langage de script serveur (pas de possibilit d'utiliser plusieurs langages de script serveur au sein d'une mme page). Interprtation des scripts ct serveur L'interprtation des scripts ct serveur est effectu par le serveur Web.
115
Karim Kalti
1- Le navigateur (client) demande une page Web dynamique en envoyant son URL au serveur l'aide du protocole HTTP. 2- Le serveur recherche la page et reconnat qu'elle contient un script serveur (d'aprs son extension). 3- Le serveur analyse le code de la page : a. Il laisse intacte les parties codes en HTML. b. Il interprte le script serveur et gnre dynamiquement un code HTML quivalent. 4- Le serveur envoie la page (qui contient du HTML seulement) au client via le protocole HTTP. 5- Le navigateur du client reoit la rponse du serveur, interprte le code HTML reu et affiche la page qui rsulte de cette interprtation.
Langages de scripts ct serveur Il existe une panoplie de langages de script ct serveur. Mais actuellement trois sont les plus utiliss : ASP.NET, PHP, JSP. Acronyme de ASP JSP PHP
Active Server Pages Java Server Pages Pre Hypertext Processor
Propritaire
Microsoft Sun Open source
Langage de programmation
C#, VB, C++ , ... Java PHP proche du C
Plateforme
Windows, (Linux projet en cours) Linux, Solaris, Windows, Linux, Solaris, Windows,
Serveur Web
IIS IIS, Apache, Tomcat, IIS, Apache,
116
Karim Kalti
ASP.NET
Introduction
ASP.NET est la nouvelle technologie propose par MS pour le dveloppement d'applications Web dynamiques. ASP.NET est diffrent de ASP (une nouvelle conception Architecture diffrente). ASP.NET fait partie du .NET FrameWork. Les langages de dveloppement : VB, C#, C++,
VB
C++
C#
JScript
Common Language Specification ASP.NET: Web Services and Web Forms Windows Forms
ADO.NET: Data and XML .NET Framework Base Classes Common Language Runtime
Caractristiques de ASP.NET
Permet le dveloppement ct serveur d'applications Web dynamiques. Programmation oriente objet. Accs toute l'API du .NET FrameWork. Introduction des contrles Web ct serveur. (Facilit de programmation et adaptation dynamique aux navigateurs clients). Possibilit de programmer avec diffrents langages. Intgration avec ADO.NET pour l'accs aux donnes. Prise en charge complte de XML. Mcanisme intgr pour mettre en cache les pages Web les plus frquemment rclames au serveur. ASP permet de dvelopper des pages interprtes alors que ASP.NET permet de dvelopper des applications compils ( l'aide de la technique du code behind) donc plus rapides que celles dveloppes avec ASP.
117
Karim Kalti
ASP.NET a t conu de faon permettre la sparation entre le code de traitement et l'interface. Ce code de traitement peut tre plac dans des fichiers sources C# (*.cs) ou Visual Basic (*.vb) lis aux fichiers des interfaces (*.aspx).
Fichiers HTML
Fichiers ASPX
Fichiers CS
Contrle Utilisateur
Une page aspx comporte : Des scripts ASP.Net crits en VB ou en C# ou en tout autre langage support par le .NET. Du HTML pour le formatage du contenu statique et ventuellement du javascript pour effectuer des traitements ct client.
118
Karim Kalti
Commentaires : Suite sa premire demande une page ASP.NET est compile puis mise en cache. Toute nouvelle demande de cette page va engendrer l'envoi direct du cache sans ncessiter une recompilation sauf si une mise jour de la page est ncessaire. La mise jour dont il est question ici concerne le code de traitement et de gnration associ la page. La saisie des donnes d'un formulaire ne demande pas une recompilation, le code de traitement et de gnration tant en effet toujours le mme (c'est comme la saisie des donnes pour un formulaire Windows, elle ne demande pas la recompilation et la gnration d'un nouvel excutable). Remarque : Si le fichier consult est un fichier aspx alors le client (le navigateur dans ce cas) reoit de la part du serveur une page. Si le fichier consult est un fichier asmx alors le client (une application web dans ce cas) reoit de la part du serveur un objet.
Balise
<% = %> <% # %> <script > </script> <asp:NomControl > </asp:NomControl>
Utilisation
Pour l'affichage de la valeur d'une expression. Cette expression doit renvoyer une chane de caractres. Ces expressions peuvent tre des variables simples ou des appels des fonctions (fonctions de l'API .NET ou personnalises). La valeur de l'expression est concatne avec le contenu statique format en HTML Pour l'affichage du contenu des variables seulement (variables chanes de caractres). Pour l'insertion des scripts. Les scripts doivent figurer dans la partie entte de la page. Pour l'insertion des contrles Web dans un formulaire serveur.
119
Karim Kalti
Commentaires : L'expression en question ici est un appel d'une fonction. Ce code montre comment appeler une fonction prdfinie du .NET et comment concatner sa valeur de retour avec un contenu statique. La mthode ToString de cet objet est surcharge. La version utilise permet de spcifier le format d'affichage de la date. Il n'est pas ncessaire de spcifier le langage car le code de l'appel s'crit de la mme manire en VB et en C# (Fonction .NET). Rsultat : (heure sur le serveur)
Il est 23:39:33
Code HTML reu par le navigateur : Suite la rception d'une demande de la page, le serveur Web interprte le script ASP.NET et gnre du HTML qu'il insre avec le flux HTML renvoy au client.
<html> <head> <title>Exemple 1 ASP.NET </title> </head> <body> Il est 23:39:33 </body> </html>
Insertion de modules de scripts Si le contenu dynamique ncessite la dfinition de modules de scripts (fonctions) alors ces modules doivent tre insrs dans la page dans une zone part, dfinie par les balises <script> </script>, et se trouvant dans la partie entte de la page. L'appel de ces fonctions dans le corps de la page peut toujours se faire en utilisant la balise <% = %>. Cette technique permet une meilleure organisation du code source de la page en sparant les scripts de gnration de contenu, du code HTML permettant le formatage de ce contenu. Exemple :
<html> <head> <script language= "c#" runat= "server"> string Demain() { DateTime aujourdhui=DateTime.Now ; DateTime demain=aujourdhui.AddDays(1) ; return demain.ToString() ; } </script> </head> <body> Date du jour : <% =DateTime.Now.ToString() %><br> Date de demain : <% =Demain() %> </body> </html>
120
Karim Kalti
Commentaires : L'attribut language dsigne le langage utilis pour crire les scripts ASP.NET. Les deux langages les plus utiliss sont C# et VB. Il n'est pas possible d'utiliser deux langages diffrents dans la mme page. La valeur server de l'attribut runat indique au serveur Web que le script doit tre excut sur le serveur. Le client recevra seulement du HTML. Rsultat : Date du jour : 24/01/2003 23:51:45 Date de demain : 25/01/2003 23:51:45 Affichage du contenu d'une variable. La valeur d'une variable peut tre insre dans le flux HTML l'aide de la balise <%# La variable doit tre de type chane ou convertie en chane. Il faut faire un Binding lors du chargement de la page. %>.
Exemple :
<html> <script language= "c#" runat= "server"> string s = "bonjour"; void Page_Load(Object sender, EventArgs e) { DataBind();} </script> <body> le contenu de la variable est : <%# s %> </body> </html>
121
Karim Kalti
Rsultat :
Nous sommes le : 25/01/2003 00:10:41
using System; public class LaDate : System.Web.UI.Page { protected DateTime aujourdhui; protected DateTime demain;
122
Karim Kalti
Fichier Test.aspx
<%@ Page Language="C#" Src="Page1.cs" Inherits="LaDate"%> <html> <body> Date de demain : <% =Demain() %> </body> </html>
Commentaires : Le fichier Page1.cs Ce fichier contient la dfinition d'une classe LaDate qui contient le code permettant de dterminer la date recherche (script de la partie traitement). Ce fichier est entirement crit en C# (aucune rfrence l'interface). La classe Page est la classe de base de toute page Web crite en ASP.NET. La classe LaDate hrite de la classe Page. Le fichier Test.aspx Le fichier Test.aspx contient le code permettant de gnrer le contenu de la page (la partie interface). Ce fichier contient un appel la fonction Demain( ) qui n'est pas dfinie dans ce fichier mais dans le fichier associ nomm Page1.cs. La directive @Page au dbut du fichier Test.aspx indique au serveur que la page Test en tant qu'objet est base sur le modle de page (hritage) dfinie par la classe LaDate. Cette directive spcifie galement le langage de programmation (Language="C#") et le fichier source dans lequel est dfinie la classe LaDate (Src="Page1.cs"). La dfinition de l'objet qui reprsente la page Test est transparente pour le programmeur. Grce au lien d'hritage avec la classe LaDate, cet objet peut utiliser directement les mthodes et proprits de cette classe et des classes sur lesquelles elle se base. Ceci explique la possibilit de l'appel directe de la fonction Demain( ) dans Test.aspx.
123
Karim Kalti
124
Karim Kalti
Classes Contient la majorit des objets qui composent une application Web comme les objets : Application, Browser, Cookies, Exception, Request, Response, Server et Trace. Contient les objets permettant de grer l'tat d'une session comme l'objet Session. Contient les objets qui permettent de crer et d'exploiter des services Web. Contient les objets qui permettent de contrler l'interface comme les objets Page et Control. Contient les objets contrles serveur utiliss dans les formulaires Web. Contient essentiellement la classe Cache qui sert mettre en uvre un cache ct serveur afin d'amliorer les performances de l'application. Contient les objets MailMessage, MailAttachement et SmtpMail qui servent envoyer des courriers lectroniques. Contient les objets et les modules d'authentification. Ils servent authentifier les utilisateurs afin de renforcer la scurit des applications.
L'objet Page
Un fichier aspx reprsente une page Web qui comporte gnralement un formulaire Web gnr et trait ct serveur. L'accs par programmation cette page se fait l'aide de l'objet Page de ASP.NET. Chaque demande d'une page aspx par un client engendre la cration sur le serveur d'une instance de l'objet Page base sur la page demande. Cycle de vie d'une page aspx Le cycle de vie d'une page Web est comme suit : Le client demande une page (fichier aspx). Le serveur Web : o localise le fichier aspx sur le serveur. o Cre en mmoire une instance Page partir du fichier aspx. o Gnre la rponse sous forme de code HTML. o Transmet cette rponse au navigateur. o Dtruit l'instance de l'objet Page sur le serveur (pas le fichier aspx). Espace de noms : System.Web.UI Constructeurs :
public Page();
Signification
Donne accs l'tat de l'application en cours. Donne accs l'objet Cache associ l'application. Contient la collection des contrles Web de la page. Donne accs l'objet Request de la requte en cours. Donne accs l'objet Response de la rponse en cours. Donne accs l'objet Server. Donne accs l'objet Session. Obtient ou dfinit une valeur indiquant si l'objet Page est rendu. Obtient ou dfinit une valeur indiquant si la page conserve son tat d'affichage, ainsi que celui de tous les contrles serveur qu'elle contient, la fin de la demande de la page en cours. Obtient une valeur indiquant si la page est en cours de chargement en rponse une publication du client ou en rponse une premire demande d'accs.
IsPostBack
bool
125
Karim Kalti
Signification
Lie une source de donnes au contrle serveur appel et tous ses contrles enfants. Retourne le chemin physique d'un chemin virtuel pass comme argument.
Principaux vnements : Les principaux vnements d'un objet Page sont cits dans le tableau suivant :
Evnement
Type de dlgation
Gestionnaire
Signification
Cet vnement se dclenche lorsqu'un contrle est charg en mmoire et initialis partir de ses proprits spcifies au moment de la dfinition de l'objet qui reprsente ce contrle. Il n'est pas possible d'accder aux autres contrles durant cet vnement (ces derniers ne sont pas ncessairement dj crs). Pour cette raison, il n'est pas possible d'agir sur les proprits des contrles pour dfinir la disposition par exemple. Cet vnement se dclenche lorsque le contrle courant et tous ses contrles enfants (La page et tous ses contrles serveur) ont t chargs en mmoire (aprs l'vnement Init). Il est possible dans ce cas d'accder ces contrles et d'agir sur leurs proprits pour faire une initialisation dynamique par exemple. Cet vnement se dclenche lorsque la page se dcharge de la mmoire. Il est exploit pour librer les ressources utilises par le contrle (fermeture des fichiers et des connexions aux bases de donnes, ). L'accs aux contrles enfants est encore possible ce niveau. Cet vnement se dclenche lorsque la page est dtruite (l'accs aux contrles enfants n'est pas sr). C'est le dernier vnement dans le cycle de vie d'une page. Se dclenche lorsqu'une exception non gre se produit dans le code de l'objet qui reprsente la page.
Init
EventHandler
Page_Init
Load
EventHandler
Page_Load
Unload
EventHandler
Page_Unload
Disposed
EventHandler
Page_Disposed
Error
EventHandler
Page_Error
Sur le plan pratique l'vnement Load est l'vnement le plus trait. A part l'vnement Error, l'ordre d'occurrence des autres vnements suit l'ordre de leur apparition dans le tableau ci-dessus.
Un contrle Web ct serveur est insr dans un formulaire Web l'aide de la balise : <asp:Nomcontrle> </asp:Nomcontrle>.
126
Karim Kalti
Les contrles Web les plus utiliss fournis par le FrameWork .NET sont rsums dans le tableau suivant : Evnements frquemment utiliss
Les vnements sont rarement utiliss. TextChanged Les vnements sont rarement utiliss. Click, Command (click avec argument). Click
Composant
Label TextBox Image Button ImageButton
Fonctionnalit
Affichage de texte. Le texte peut inclure des balises html. Zone d'dition. Affichage d'une image. Bouton de commande. Bouton de commande avec image. Lien hypertexte pour la navigation Web. Le transfert vers la page de destination est direct partir du client sans passage par le serveur. Panneau permettant de dposer d'autres composants. Case cocher. Case options. Bote de liste. Bote combo (Liste droulante). Bote de liste avec case cocher pour chaque ligne.
HyperLink
Les vnements sont rarement utiliss. Les vnements sont rarement utiliss. CheckChanged CheckChanged SelectedIndexChanged SelectedIndexChanged CheckChanged CancelCommand, EditCommand, DeleteCommand, ItemCommand, SelectedIndexChanged, PageIndexChanged, SortCommand, UpdateCommand, ItemCreated, ItemDataBound
DataGrid
Grille de donnes.
127
Karim Kalti
<html> <head> </head> <body> <form runat="server"> <p> <asp:Label id="LbE1" runat="server">Entier 1 : </asp:Label> <asp:TextBox id="TxtBE1" runat="server"></asp:TextBox> <br/> <asp:Label id="LbE2" runat="server">Entier 2 : </asp:Label> <asp:TextBox id="TxtBE2" runat="server"></asp:TextBox> <br /> <asp:Button id="BtnSomme" onclick="BtnSomme_Click" runat="server" Text="Somme"></asp:Button> <br /> <asp:Label id="LbResultat" runat="server">La somme est : </asp:Label> </p> </form> </body> </html>
Rsultat de l'excution
Organisation gnrale du code La premire ligne de code du fichier <%@ Page Language="C#" %> est une directive qui indique qu'il s'agit d'une page aspx et que le langage utilis par cette page est le C#. Le reste du code source du fichier est divis en deux parties : o La premire partie, dfinie dans l'entte de la page et dlimite par les balises <script runat="server"> </script>, reprsente un script C# qui dfinit les traitements effectus par le formulaire. o La deuxime partie dfinie dans le corps de la page, reprsente le code ncessaire la cration de la prsentation de la page (Interface). Cette partie comporte essentiellement un formulaire Web.
Ajout du formulaire la page Le formulaire Web est ajout la page l'aide de la paire de balises <form runat="server"> </form>. L'attribut runat="server" indique que le formulaire Web est un formulaire qui doit tre trait sur le serveur.
128
Karim Kalti
Ajout d'un contrle au formulaire L'ajout des contrles Web au formulaire se fait l'aide de la balise : <asp:Nomcontrle . . .> </asp:Nomcontrle.>. Exemple : Cet exemple montre l'ajout d'un bouton au formulaire :
<asp:Button id="BtnSomme" onclick="BtnSomme_Click" runat="server" Text="Somme"></asp:Button>
asp:Button : indique que le contrle est un bouton. L'attribut Id permet de spcifier l'identifiant du bouton. L'attribut onclick permet de spcifier le gestionnaire de l'vnement clic sur le bouton. Dans l'exemple courant ce gestionnaire est BtnSomme_Click. L'attribut Runat="Server" : indique que le bouton est gr ct serveur. L'attribut Text permet de spcifier le texte qui sera affich sur le bouton. Modle de l'objet instanci en mmoire lors de la demande de la page La demande d'une page aspx comportant un formulaire Web par un client va engendrer la cration ct serveur d'une instance d'un objet bas sur cette page et d'un ensemble d'instances des objets reprsentant les contrles serveur composant le formulaire. L'objet qui reprsente la page hrite de l'objet Page de ASP.NET. Les instances des contrles Web sont associes cet objet sous forme d'attributs. Les identifiants des contrles spcifis par l'attribut Id permettent de rfrencer les instances de ces contrles. Pour l'exemple courant la structure de l'objet instanci en mmoire suite la demande de la page Test.aspx ressemble ceci : Page
Test
Button BtnSomme; Label LbResultat; Label LbE1; Label LbE2; TextBox TxtBE1; TextBox TxtBE2;
129
Karim Kalti
130
Karim Kalti
</script> <html> <head> </head> <body> <form runat="server"> <p> <asp:Label id="LbE1" runat="server">Entier 1 : </asp:Label> <asp:TextBox id="TxtBE1" runat="server"></asp:TextBox> <br /> <asp:Label id="LbE2" runat="server">Entier 2 : </asp:Label> <asp:TextBox id="TxtBE2" runat="server"></asp:TextBox> <br /> <asp:Button id="BtnSomme" onclick="BtnSomme_Click" runat="server" Text="Somme"> </asp:Button> <br/> <asp:Label id="LbResultat" runat="server">La somme est : </asp:Label> </p> </form> </body> </html>
Remarque : Un fichier aspx inclut par dfaut les espaces de noms les plus frquemment utiliss lors de la cration d'une page Web. Ces espaces de noms sont : System, System.Web, System.Web.UI, System.Web.UI.WebControls. Ceci explique d'ailleurs la possibilit d'utilisation directe des objets "Contrles Web", des exceptions, etc. Version "code behind" du code prcdent Fichier Test.aspx
<%@ Page Language="C#" Src="Page1.cs" Inherits="Test.Page1" %> <html> <head> </head> <body> <form runat="server"> <p> <asp:Label id="LbE1" runat="server">Entier 1 : </asp:Label> <asp:TextBox id="TxtBE1" runat="server"></asp:TextBox> <br /> <asp:Label id="LbE2" runat="server">Entier 2 : </asp:Label> <asp:TextBox id="TxtBE2" runat="server"></asp:TextBox> <br /> <asp:Button id="BtnSomme" onclick="BtnSomme_Click" runat="server" Text="Somme"></asp:Button> <br /> <asp:Label id="LbResultat" runat="server">La somme est : </asp:Label> </p> </form> </body> </html>
Fichier Page1.cs
namespace { using using using using Test System; System.Web; System.Web.UI; System.Web.UI.WebControls;
public class Page1 : Page { // Rfrences aux contrles dfinis dans le fichier aspx public Label LbE1; public Label LbE2; public Label LbResultat; public TextBox TxtBE1; public TextBox TxtBE2;
131
Karim Kalti
public Button BtnSomme; protected void Page_Load(object sender, EventArgs e) { if( IsPostBack == false) { TxtBE1.Text="0"; TxtBE2.Text="0"; } } public void BtnSomme_Click(object sender, EventArgs e) { int Somme; if(TxtBE1.Text!="" && TxtBE2.Text!="") { try { Somme = Int32.Parse(TxtBE1.Text)+Int32.Parse(TxtBE2.Text); LbResultat.Text = "La somme est :" + Somme.ToString(); } catch(Exception) { LbResultat.Text = "Prire de vrifier les valeurs saisies";} } } } }
Remarque : Aucun espace de noms n'est inclut par dfaut dans un fichier .cs. C'est pourquoi, il est ncessaire de mentionner explicitement les espaces de noms utiliss dans ce type de fichier.
La classe Control
Cette classe est la classe de base de tous les contrles. (Web Controls et HTML Controls). Principales proprits : Proprit Type
ID Page Parent Controls string Page Control ControlCollection
Signification
Tout composant peut porter un nom, ce nom est lId. Cest partir de ce nom qu'il est possible de modifier les attributs du contrle dans du code c# . Il est interdit d'avoir deux fois le mme Id dans une mme page asp.NET. Obtient une rfrence l'instance de Page qui contient le contrle serveur. Obtient une rfrence au contrle parent du contrle serveur dans la hirarchie des contrles de la page. Obtient un objet ControlCollection qui reprsente les contrles enfants d'un contrle serveur spcifi dans la hirarchie de l'interface utilisateur. Obtient ou dfinit une valeur indiquant si le contrle serveur rend persistant son tat d'affichage, ainsi que celui de tous les contrles enfants qu'il contient, sur le client l'origine de la demande. Obtient ou dfinit une valeur qui indique si un contrle serveur est rendu sous la forme d'une interface utilisateur sur la page.
EnableViewState
Bool
Visible
bool
Signification
Lie une source de donnes au contrle serveur appel et tous ses contrles enfants. Permet un contrle serveur d'effectuer le nettoyage final avant qu'il soit libr de la mmoire. Dtermine si le contrle serveur contient des contrles enfants.
Type de dlgation
EventHandler
Signification
Cet vnement se dclenche lorsqu'un contrle est charg en mmoire et initialis partir de ses proprits spcifies au moment de la dfinition de l'objet qui reprsente ce contrle. Il n'est pas possible d'accder aux autres contrles durant cet vnement
132
Karim Kalti
Load
EventHandler
Unload Disposed
EventHandler EventHandler
(ces derniers ne sont pas ncessairement dj crs). Pour cette raison, il n'est pas possible d'agir sur les proprits des contrles pour dfinir la disposition par exemple. Cet vnement se dclenche lorsque le contrle courant et tous ses contrles enfants ont t chargs en mmoire (aprs l'vnement Init). Il est possible dans ce cas d'accder ces contrles et d'agir sur leurs proprits pour faire une initialisation dynamique par exemple. Cet vnement se dclenche lorsque le contrle se dcharge de la mmoire. Il est exploit pour librer les ressources utilises par le contrle. Cet vnement se dclenche lorsque le contrle est dtruit.
La classe WebControl
Cette classe est la classe de base de tous les contrles Web ct serveur. Elle dfinit les mthodes, proprits et vnements communs tous ces contrles. Espace de noms : System.Web.UI.WebControls Classes drives
System.Object System.Web.UI.Control System.Web.UI.WebControls.WebControl System.Web.UI.WebControls.AdRotator System.Web.UI.WebControls.BaseDataList System.Web.UI.WebControls.Button System.Web.UI.WebControls.Calendar System.Web.UI.WebControls.CheckBox System.Web.UI.WebControls.DataListItem System.Web.UI.WebControls.HyperLink System.Web.UI.WebControls.Image System.Web.UI.WebControls.Label System.Web.UI.WebControls.LinkButton System.Web.UI.WebControls.ListControl System.Web.UI.WebControls.Panel System.Web.UI.WebControls.Table System.Web.UI.WebControls.TableCell System.Web.UI.WebControls.TableRow System.Web.UI.WebControls.TextBox System.Web.UI.WebControls.ValidationSummary
Type
string enum Color Uint enum BorderStyle bool enum Color Uint short Uint
Signification
C'est la touche servant d'acclrateur (en combinaison avec ALT) pour excuter l'vnement click sur le contrle. (Exemple AccessKey='A', ALT+A). Couleur d'arrire plan du contrle. Epaisseur de la bordure. Type de contour. Les valeurs possibles sont celles de l'numration BorderStyle. Indique si le contrle est activ ou non. Couleur d'avant plan du texte. Hauteur du contrle en pixels. Ordre du passage du focus d'entre par les touches de tabulation. Largeur du contrle en pixels.
133
Karim Kalti
L'objet HttpApplication
L'objet HttpApplication se situe au sommet de la hirarchie des objets d'une application Web ASP.NET. Il permet la configuration et la sauvegarde des informations d'tat au niveau de l'application et au niveau des sessions. L'objet HttpApplication permet travers ses proprits d'accder aux diffrents autres objets composant une application Web. Le tableau suivant prsente quelques exemples de ces objets : Proprit
Application Session Request Response
Type
HttpApplicationState HttpSessionState HttpRequest HttpResponse
Signification
Permet de sauvegarder des donnes ayant une porte au niveau "Application". Permet de sauvegarder des donnes ayant une porte au niveau "Session". Donne accs l'objet Request qui reprsente la requte courante de l'utilisateur. Donne accs l'objet Response qui reprsente la rponse courante envoye par le serveur au client. Cette proprit donne accs l'objet Server qui fournit des mthodes trs pratiques pour l'encodage et le dcodage des URL et pour la rcupration d'informations sur le serveur.
Server
HttpServerUtility
Chaque application Web est reprsente par un objet qui drive de la classe HttpApplication. Cet objet appel gnralement Global est automatiquement instanci au moment du dmarrage de l'application Web et est libr lorsque cette dernire se termine. L'objet Global est dfini dans un fichier particulier appel Global.asax de la manire suivante :
public class Global : System.Web.HttpApplication { . . .}
L'objet HttpRequest
L'objet HttpRequest contient les informations renvoyes par le client (navigateur) lorsque ce dernier demande une page de l'application. L'objet HttpRequest possde des proprits qui permettent d'accder d'autres objets et informations susceptibles d'accompagner la requte du client. Le tableau suivant prsente quelques exemples de ces proprits : Proprit
Browser Cookies Files InputStream ApplicationPath URL UserHostAdress
Type
HttpBrowserCapabilities HttpCookieCollection HttpFileCollection Stream String classe Uri string
Signification
Permet de rcuprer des informations sur le browser du client ayant mis la requte. Permet de rcuprer une collection de cookies partir du client. Reoit les fichiers tlchargs du client vers le serveur. Permet d'avoir accs au contenu du corps de la requte http adresse au serveur. Retourne le chemin virtuel de l'application sur le serveur Retourne l'url de la requte courante. La classe Uri permet d'avoir une reprsentation objet de l'url. Retourne l'adresse IP d'un client distant. Contient la collection de paramtres qui accompagne la requte. L'accs un paramtre donn se fait l'aide d'un indexeur de la collection qui prend comme argument le nom du paramtre et qui retourne sa valeur.
Params
NameValueCollection
L'accs par programmation l'instance de la classe HttpRequest qui reprsente la requte courante adresse au serveur se fait travers la proprit Request de l'objet Global automatiquement instanci par drivation de la classe HttpApplication lors du dmarrage de l'application. Le fait que l'objet Global soit global, rend galement l'objet Request global et directement accessible partir de n'importe quelle page de l'application Web.
134
Karim Kalti
Exemple 2 : Rcuprer les donnes d'un GET Pour rappel, Il existe deux mthodes permettant d'envoyer les donnes d'un formulaire d'une page Web vers le serveur. La mthode GET : qui engendre un envoi des donnes avec l'url. L'url ressemble alors ceci :
http://NomDomaine/PageScript?champ1=valeur1&champ2=valeur2&champ3=valeur3
La mthode POST : qui engendre un envoi des donnes dans le corps de la requte. Le choix de la mthode d'envoi est spcifi dans la balise d'ajout du formulaire comme suit :
<form id="Form1" method="GET" runat="server">
On considre l'url : http://NomDomaine/PageScript?champ1=valeur1&champ2=valeur2&champ3=valeur3 La rcupration de la valeur du champ1 du formulaire se fait comme suit :
Request.Params["champ1"]
L'objet HttpResponse
L'objet HttpResponse sert constituer le flux HTML envoy par le serveur au client (navigateur) en rponse une requte de ce dernier. L'objet HttpResponse possde des proprits permettant d'accder d'autres objets qui peuvent accompagns ou tre utiliss par la rponse. Le tableau suivant prsente quelques exemples de ces proprits : Proprit
Cache Cookies OutputStream
Type
HttpCachePolicy HttpCookieCollection Stream
Signification
Dtermine la manire avec laquelle le serveur met en cache la rponse (la page) avant de l'envoyer au client. Dfinit le contenu du cookie qui est envoy au client. Permet d'avoir accs au flux qui contient les donnes brutes qui composent la rponse envoye au client.
La classe HttpResponse possde quelques mthodes intressantes qui sont prsentes dans le tableau suivant : Mthode
void Clear() void Redirect(string) void Write(string s)
Signification
Efface le contenu de la rponse (le flux OutputStream). Redirige le client vers l'url spcifie comme argument. Ecrit la chane s dans le flux constituant la rponse.
L'accs par programmation l'instance de la classe HttpResponse qui reprsente la rponse courante du serveur se fait travers la proprit Response de l'objet Global automatiquement instanci par drivation de la classe HttpApplication lors du dmarrage de l'application. Le fait que l'objet Global soit global, rend galement l'objet Response global et directement accessible partir de n'importe quelle page de l'application Web.
135
Karim Kalti
Exemple 1 : Ecriture d'un texte dans une page Web. ASP.NET fournit un moyen d'insrer directement du texte dans la rponse renvoye au client et ce l'aide de la mthode Write de la classe HttpResponse. Cette mthode est similaire la fonction echo de PHP ou la mthode Response.Write de l'ASP (la version avant .NET). La mthode Write est utilise comme suit :
Resposne.Write ("Ceci est un programme ASP.NET");
Toutefois ASP.NET fournit une autre alternative pour afficher le texte dans une page web et qui consiste dans l'utilisation des contrles Web ct serveur et notamment le contrle Label. Exemple 2 : Redirection L'objet Response fournit le moyen d'effectuer une redirection par programmation et ce l'aide de la mthode Redirect.
Response.Redirect("NouvellePage.aspx");
Exemple d'application : contrle d'accs (passage d'arguments travers l'url) Fichier LogPw.aspx
<html> <head> <%@ Page Language="C#" %> <script runat="server"> public void Check(object sender, EventArgs e) { string[,] tab={{"ali","a1"},{"salah","s1"}}; int i=0; while (i<2) { if (TbLogin.Text == tab[i,0] && TbPasswd.Text == tab[i,1]) Response.Redirect("MesInfos.aspx?Lg=" + TbLogin.Text +"&Pw=" + TbPasswd.Text); i++; } Response.Write("Veuillez saisir une autre fois le login et le password!!"); } </script> </head> <body> <form runat="server"> Login:    <asp:TextBox id="TbLogin" Runat="server"></asp:TextBox><br/> Passwd: <asp:TextBox id="TbPasswd" Runat="server"></asp:TextBox><br/><br/> <asp:Button id="BuLogin" onclick="Check" Runat="server" Text="Login"></asp:Button> </form> </body> </html>
136
Karim Kalti
Fichier MesInfos.aspx
<html> <head> <%@ Page Language="C#" %> <script runat="server"> void Page_Load(object sender, EventArgs e) { if (Request.Params["Lg"]!=null) La.Text = "<br><b>Login :</b> " + Request.Params["Lg"].ToString(); if (Request.Params["Pw"]!=null) La.Text += "<br><b>Password :</b> " + Request.Params["Pw"].ToString(); } </script> </head> <body> <form runat="server"> Page MesInfos<br> <asp:Label Runat=server ID=La></asp:Label> </form> </body> </html>
LogPw.aspx
MesInfos.aspx
L'objet HttpApplicationState
Rappel : Une application Web dmarre lors de l'ouverture d'une premire session par un client. Une application Web peut avoir plusieurs sessions ouvertes en mme temps. Une session se termine aprs l'coulement d'une priode d'attente paramtrable (Timeout) aprs la fermeture du navigateur ou l'annulation de la session par programmation. Une application Web se termine suite l'coulement d'une priode d'attente paramtrable (Timeout) aprs la terminaison de la dernire session ouverte de l'application. Les variables d'application Lors du dveloppement d'une application Web, il est souvent utile de dclarer des variables ou des objets qui ont une porte globale (visibles dans toute l'application Web). Ces objets sont partags par toutes les pages de toutes les sessions d'une application. Ils sont appels des variables d'application. La classe HttpApplicationState permet de grer les variables d'application. Proprit
Count
Type
Int
Signification
Donne le nombre d'objets stocks dans l'tat Application (le nombre de variables d'application). Indexeur permettant d'accder aux diffrents objets stocks dans l'tat Application. L'index peut tre numrique ou une chane qui reprsente le nom de l'objet auquel on veut accder.
Item
Indexeur []
137
Karim Kalti
Mthode
void Add(string name, object value); void Clear() void Remove(string name) void RemoveAt(int index) void Lock() void Unlock()
Signification
Ajoute l'objet dont le nom est "name" et la valeur est "value" la collection des variables d'application. Supprime tous les objets de la collection de variables d'application. Supprime l'objet dont le nom est pass comme argument de la collection de variables d'application. Supprime l'objet dont l'index numrique est pass comme argument de la collection de variables d'application. Effectue un verrouillage de l'tat d'application afin de faciliter la synchronisation des accs aux variables d'application. Effectue un dverrouillage de l'tat d'application afin de faciliter la synchronisation des accs aux variables d'application.
L'accs par programmation l'instance de la classe HttpApplicationState qui reprsente l'tat de l'application courante se fait travers la proprit Application de l'objet Global automatiquement instanci par drivation de la classe HttpApplication lors du dmarrage de l'application. Le fait que l'objet Global soit global, rend galement l'objet Application global et directement accessible partir de n'importe quelle page de l'application Web. Utilisation des variables d'application La classe HttpApplicationState offre la possibilit de dclarer des variables qui sont accessibles partir de n'importe quel endroit d'une application Web par toutes les sessions ouvertes. Ces variables sont dites des variables d'application. La cration d'une variable d'application se fait au vol sans dclaration explicite, ni spcification de type. La syntaxe utilise pour faire cette cration est : Application["NomVariable"] = Valeur; La cration d'une variable d'application peut se faire n'importe o dans une application Web. Toutefois l'endroit qui est gnralement utilis pour faire cette cration est le gestionnaire Application_Start dans le fichier Global.asax. Exemple :
<%@ Page Language="C#" %> <script runat="server"> void Page_Load(object sender, EventArgs e) { if(Application["DerniereOffre"]!=null) LbDerniereOffre.Text ="La dernire offre est :"+Application["DerniereOffre"]; } void BtnRafraichir_Click(object sender, EventArgs e) { Response.Redirect("Offre.aspx"); } void BtnEnvoyer_Click(object sender, EventArgs e) { if(TxtBProposer.Text!="") { Application["DerniereOffre"]=TxtBProposer.Text; LbDerniereOffre.Text ="La dernire offre est :"+Application["DerniereOffre"]; } } </script> <html> <head> </head> <body> <form runat="server"> <p> <asp:Label id="LbDerniereOffre" runat="server" width="265px">dernire offre: </asp:Label> <br /> <asp:Button id="BtnRafraichir" onclick="BtnRafraichir_Click" runat="server" Width="100px" Text="Rafrachir" Height="25px"></asp:Button> </p> <p>
138
Karim Kalti
<asp:Label id="LbProposer" runat="server">Proposer une offre :</asp:Label> <asp:TextBox id="TxtBProposer" runat="server"></asp:TextBox><br /> <asp:Button id="BtnEnvoyer" onclick="BtnEnvoyer_Click" runat="server" Width="100px" Text="Envoyer" Height="25px"></asp:Button> </p> </form> </body> </html>
Commentaire : Ce code cre une interface qui permet diffrents utilisateurs de proposer des offres (des entiers numriques) et de voir chaque fois la dernire offre propose (bouton Rafrachir).
Synchronisation des accs une variable d'application : Le fait que les variables d'application soient partages par toutes les sessions peut engendrer des problmes lors des tentatives d'accs simultans ces variables par plusieurs utilisateurs. Par exemple un utilisateur accde une variable d'application et commence faire des traitements avec et entre temps un autre utilisateur accde cette variable et modifie son contenu. Pour viter ce genre de problme, il faut synchroniser les oprations d'accs l'aide des mthodes Lock et Unlock. Exemple :
. . . Application.Lock(); Application["DerniereOffre"]=TxtBProposer.Text; LbDerniereOffre.Text ="La Dernire offre est :"+Application["DerniereOffre"]; Application.UnLock(); . . .
L'objet HttpSessionState
Les variables de session Outre les variables d'application, il existe une autre catgorie de variables globales qui peut tre trs utile lors du dveloppement d'une application Web. Il s'agit des variables qui ont pour porte une session et qui sont appeles de ce fait les variables de session. Une variable de session est partage par toutes les pages d'une application Web mais pour une session donne. La classe HttpSessionState permet de grer les variables et les paramtres relatifs une session donne. Proprit
Count Item SessionID TimeOut
Type
Int Indexeur [] String Int
Signification
Donne le nombre d'lments stocks dans l'tat d'une session. Indexeur permettant d'accder aux diffrents lments stocks dans l'tat d'une session. L'index peut tre numrique ou une chane qui reprsente le nom de l'lment auquel on veut accder. Rcupre un ID permettant d'identifier d'une manire unique une session. Dtermine le temps d'attente (en minutes) qu'il ne faut pas dpasser entre deux requtes avant qu'une session ne soit termine.
Mthode
void Add(string name, object value);
Signification
Ajoute l'objet dont le nom est "name" et la valeur est "value" la
139
Karim Kalti
void Abandon() void Clear() void Remove(string name) void RemoveAt(int index)
collection des variables de session. Annule la session en cours. Supprime tous les objets de la collection de variables de session. Supprime l'objet dont le nom est pass comme argument de la collection de variables de session. Supprime l'objet dont l'index numrique est pass comme argument de la collection de variables de session.
L'accs par programmation l'instance de la classe HttpSessionState qui reprsente l'tat de la session courante se fait travers la proprit Session de l'objet Global. Le fait que l'objet Global soit global, rend galement l'objet Session global et directement accessible partir de n'importe quelle page de l'application Web. Utilisation des variables de session : La cration d'une variable de session se fait au vol sans dclaration explicite, ni spcification de type. La syntaxe utilise pour faire cette cration est : Session["NomVariable"] = Valeur; La cration d'une variable de session peut se faire n'importe o dans une application Web. Cette variable est alors accessible partir de n'importe quelle page mais pour une session donne. L'endroit qui est gnralement utilis pour crer les variables de session est le gestionnaire Session_Start dfini dans le fichier Global.asax. Exemple : Programme "contrle d'accs" utilisant les variables de session Il s'agit du mme programme de contrle d'accs prsent prcdemment. Cette fois ce programme utilise les variables de session au lieu du passage d'arguments travers l'url. Fichier LogPw.aspx
<html> <head> <%@ Page Language="C#" %> <script runat="server"> public void Check(object sender, EventArgs e) { string[,] tab={{"ali","a1"},{"salah","s1"}}; int i=0; while (i<2) { if (TbLogin.Text == tab[i,0] && TbPasswd.Text == tab[i,1]) { Session["Lg"]=TbLogin.Text; Session["Pw"]=TbPasswd.Text; Response.Redirect("MesInfos.aspx"); } i++; } Response.Write("Veuillez saisir une autre fois le login et le password!!"); } </script> </head> <body> <form runat="server"> Login:    <asp:TextBox id="TbLogin" Runat="server"></asp:TextBox><br/> Passwd: <asp:TextBox id="TbPasswd" Runat="server"></asp:TextBox><br/><br/> <asp:Button id="BuLogin" onclick="Check" Runat="server" Text="Login"></asp:Button> </form> </body> </html>
Fichier MesInfos.aspx
140
Karim Kalti
<html> <head> <%@ Page Language="C#" %> <script runat="server"> void Page_Load(object sender, EventArgs e) { if (Session["Lg"]!=null) La.Text = "<br><b>Login :</b> " + Session["Lg"]; if (Session["Pw"]!=null) La.Text += "<br><b>Password :</b> " + Session["Pw"]; } </script> </head> <body> <form runat="server"> Page MesInfos<br><br> <asp:Label Runat=server ID=La></asp:Label> </form> </body> </html>
Remarque: Les variables de session et d'application sont stockes en mmoire sur le serveur. Il peut y avoir autant de variables que lon le dsire, cependant il ne faut pas perdre de vue quavec laccroissement du nombre de variables utilises, ce sont souvent les performances qui sont en chute libre. Il faut donc trouver le juste milieu entre performances et facilit. Les informations utilises de manire rpte, si elles nont pas un trop haut cot en mmoire, peuvent donc tre stocke dans ce type de variables (par exemple : le UserName de lutilisateur pour les variables de session, les chanes et les objets de connexion la base de donnes pour les variables d'application).
Le fichier Global.asax
Le fichier Global.asax, connu galement comme le fichier d'application, est un fichier optionnel qui contient le code permettant de grer les vnements dclenchs par une application Web ainsi que par ses sessions et ses modules. Le fichier Global.asax doit rsider toujours dans le rpertoire racine de l'application Web. Le fichier Global.asax est configur de faon ce que toute requte qui lui est adresse (url) soit rejete. Ce fichier ne peut ni tre tlcharg ni dit par un utilisateur externe. Lors du lancement d'une application Web, le fichier Global.asax est compil et ses donnes sont utilises pour gnrer dynamiquement une classe drive de la classe HttpApplication appele Global. Remarque : Le fichier Global.asax est optionnel. S'il n'est pas prsent pour une application Web alors cela suppose que cette dernire ne gre pas les vnements au niveau Application et au niveau Session. La classe Global est dans ce cas implicitement dfinie et instancie. Evnements grs dans le Global.asax Le fichier Global.asax permet d'crire le code de gestion des vnements dclenchs par une application ASP.NET et par ses modules (ventuellement des modules personnaliss). Toutefois les vnements les plus traits dans ce fichier restent ceux lis au niveau Application et au niveau Session. Les noms des gestionnaires d'vnements pour ces deux objets sont prdfinis et automatiquement reconnus par Global.asax. (Si l'attribut AutoEventWireup de l'objet Page vaut "true", true est la valeur par dfaut pour cet attribut). Le tableau suivant donne quelques exemples de gestionnaires les plus utiliss dans ce cadre ainsi qu'une description des vnements qu'ils traitent. Gestionnaire d'vnement
Application_Start ou galement Application_OnStart
Type de dlgation
EventHandler
141
Karim Kalti
EventHandler
Application_BeginRequest
EventHandler
Application_EndRequest
EventHandler
Application_Error
EventHandler
Ce gestionnaire s'excute lorsque l'application est termine. . A toute application est associ un dlai d'inactivit, configurable dans [web.config], au bout duquel l'application est considre comme termine. C'est donc le serveur web qui prend cette dcision en fonction du paramtrage de l'application. Le dlai d'inactivit d'une application est dfini comme le temps pendant lequel aucun client n'a fait une demande pour une ressource de l'application. Ce gestionnaire s'excute au dbut de chaque requte envoye par un client au serveur (demande d'une page). Ce gestionnaire peut tre exploit pour examiner la requte avant de l'envoyer la page demande. Il est mme possible de rediriger la requte vers une autre page. Ce gestionnaire s'excute la fin de chaque requte envoye par un client au serveur Ce gestionnaire s'excute chaque fois que se produit une erreur non explicitement interceptes dans le code du fichier Global.asax ou dans les fichiers .aspx et .cs. Il constitue un bon moyen pour centraliser le processus de gestion des erreurs pouvant se produire dans toute l'application. Ce gestionnaire s'excute chaque ouverture d'une nouvelle session. Ce gestionnaire s'excute la fermeture de chaque session. (la fermeture d'une session peut tre dclenche par la fermeture du navigateur, ou suite l'coulement d'un dlai d'inactivit de la session. Une page Web peut proposer galement une commande de fermeture explicite de la session l'utilisateur).
EventHandler
Session_End
EventHandler
Commentaire : La directive utilise au dbut du fichier n'est plus Page comme cela a t le cas pour les exemples prcdents mais Application : <%@ Application language="C#" %>. Avec cette directive, toutes les mthodes qui figurent dans la partie script du fichier seront compiles et ajoutes la classe Global base sur HttpApplication.
142
Karim Kalti
Version "Code behind" du fichier Global.asax Comme les fichiers aspx, le fichier Global.asax peut tre organis suivant le modle "Code Behind" et tre ainsi rparti sur deux fichiers Global.asax et Global.asax.cs. Contenu du fichier Global.asax
<%@ Application src="Global.asax.cs" Inherits="Global" %>
Exemple d'application 1 L'exemple suivant montre les diffrents moments d'appel des gestionnaires d'vnements Application_Start, Session_Start et Application_BeginRequest dfinis dans le fichier Global.asax. Fichier Global.asax :
<%@ Application language="C#" %> <script runat="server"> public void Application_Start(Object sender, EventArgs e) { Application["StartApp"] = DateTime.Now.ToString("T"); } public void Session_Start(Object sender, EventArgs e) { Session["StartSess"] = DateTime.Now.ToString("T"); } public void Application_BeginRequest(Object sender, EventArgs e) { Context.Items["StartReq"] = DateTime.Now.ToString("T"); } </script>
Fichier principal.aspx
<html> <head> <%@ Page Language="C#" Debug="true" %> <script runat="server"> string string string string jeton; startApplication; startSession; startRequest;
void Page_Load(object sender, EventArgs e) { jeton=Session.SessionID; startApplication = Application["StartApp"].ToString(); startSession = Session["StartSess"].ToString(); startRequest = Context.Items["StartReq"].ToString(); } </script>
143
Karim Kalti
</head> <body> jeton de session : <% =jeton %> <br /> dbut Application : <% =startApplication %> <br /> dbut Session : <% =startSession %> <br /> dbut Requte : <% =startRequest %> <br /> </body> </html>
Pour voir les diffrents moments d'excution des gestionnaires d'vnements lancer le fichier principal.aspx partir de plusieurs instances du navigateur sur une mme machine ou sur des machines diffrentes.
Exemple d'application 2 Cet exemple montre comment il est possible en utilisant les variables d'application de dterminer le nombre d'utilisateurs connects. Fichier Global.asax :
<%@ Application language="C#" %> <script runat="server"> public void Application_Start(Object sender, EventArgs e) { Application["NbUtilisateurs"] = 0; } public void Session_Start(Object sender, EventArgs e) { Application["NbUtilisateurs"] = Convert.ToInt32(Application["NbUtilisateurs"])+1; } public void Session_End(Object sender, EventArgs e) { Application["NbUtilisateurs"] = Convert.ToInt32(Application["NbUtilisateurs"])-1; } </script>
Fichier principal.aspx
<%@ Page Language="C#" %> <html> <head> </head> <body> Nombre d'utilisateurs connects : <% =Application["NbUtilisateurs"] %> <br /> </body> </html>
Commentaires : La fermeture du navigateur n'engendre pas la terminaison immdiate de la session. Cette dernire se termine en effet aprs l'coulement d'un Timeout paramtrable dans le fichier Web.config. (fichier de configuration d'une application Web ASP.NET) Les variables d'application et de session sont par dfaut de type object. Ceci explique d'une part la possibilit d'y placer directement des valeurs et d'autre part la ncessiter de les convertir travers un casting lorsqu'elles sont utilises dans des expressions.
144
Karim Kalti
Ouvrage
Inventaire 1 2 3 4 5 Titre AnneEdition Programmation C++ 2003 Les rseaux 2004 Les bases de donnes 1995 Java 1999 UML 2004
<%@ Page Language="C#" Debug="true" %> <%@ import Namespace="System.Data" %> <%@ import Namespace="System.Data.OleDb" %> <script runat="server"> void ClickAjouter(object sender, EventArgs e) { // Cration de la chane de connexion string StrCnn = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source ="+ // Cration de l'objet de connexion OleDbConnection cnn = new OleDbConnection(StrCnn); // Ouverture de la connexion cnn.Open(); // Texte de la commande string StrSql = "INSERT INTO Ouvrage VALUES ("+ TxtBInventaire.Text+",'"+TxtBTitre.Text+"',"+ TxtBEdition.Text+")"; // Cration de l'objet Command OleDbCommand cmd=new OleDbCommand(StrSql,cnn);
MapPath("Biblio.mdb");
145
Karim Kalti
// Excution de la commande try { cmd.ExecuteNonQuery(); } catch(Exception) { Response.Write("Erreur d'insertion"); } finally { // Fermeture de la connexion cnn.Close(); } } </script> <html> <head> </head> <body> <form runat="server"> <div align="left"><font size="7">Ajout d'ouvrages</font> </div> <div align="left"> </div> <div align="left"><asp:Label id="LbInventaire" runat="server">Inventaire : </asp:Label> <asp:TextBox id="TxtBInventaire" runat="server" Width="162px"></asp:TextBox> <br /> <asp:Label id="LbTitre" runat="server">Titre : </asp:Label> &nbs p; <asp:TextBox id="TxtBTitre" runat="server" Width="159px"></asp:TextBox> <br /> <asp:Label id="LbEdition" runat="server">Anne d'dition : </asp:Label> <asp:TextBox id="TxtBEdition" runat="server" Width="160px"></asp:TextBox> </div> <div align="left"> </div> <div align="left"> <asp:Button id="BtnAjouter" onclick="ClickAjouter" runat="server" Width="86px" Text="Ajouter"></asp:Button> </div> <!-- Insert content here --> </form> </body> </html>
146
Karim Kalti
<%@ Page Language="C#" Debug="true" %> <%@ import Namespace="System.Data" %> <%@ import Namespace="System.Data.OleDb" %> <script runat="server"> void Page_Load(object sender, EventArgs e) { string StrCnn = "Provider = Microsoft.Jet.OLEDB.4.0; ="+MapPath("Biblio.mdb"); OleDbConnection cnn = new OleDbConnection(StrCnn); string StrSql = "SELECT * FROM Ouvrage"; OleDbDataAdapter DA; DataSet DS; cnn.Open(); DA = new OleDbDataAdapter(StrSql,cnn); DS = new DataSet(); DA.Fill(DS,"LesInventaires"); DG.DataSource = DS; DG.DataMember = DS.Tables["LesInventaires"].ToString(); DG.DataBind(); } </script> <html> <head> </head> <body> <form runat="server"> <p> <font size="7">Liste des ouvrages</font> </p> <p> <font size="7"> <asp:DataGrid id="DG" runat="server" EnableViewState="False" OnLoad="Page_Load"> <HeaderStyle font-bold="True" horizontalalign="Center" forecolor="Black" verticalalign="Middle" backcolor="Silver"></HeaderStyle> <AlternatingItemStyle horizontalalign="Center" backcolor="WhiteSmoke"></AlternatingItemStyle> <ItemStyle horizontalalign="Center" verticalalign="Middle" backcolor="Beige"></ItemStyle> </asp:DataGrid> </font> </p> </form> </body> </html> Data Source
147
Karim Kalti
<%@ Page Language="C#" Debug="true" %> <%@ import Namespace="System.Data" %> <%@ import Namespace="System.Data.OleDb" %> <script runat="server"> void Page_Load(object sender, EventArgs e) { if(IsPostBack==false) { string StrCnn = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source ="+MapPath("Biblio.mdb"); OleDbConnection cnn = new OleDbConnection(StrCnn); cnn.Open(); string StrSql = "SELECT * FROM Ouvrage"; OleDbDataAdapter DA; DataSet DS; DA = new OleDbDataAdapter(StrSql,cnn); DS = new DataSet(); DA.Fill(DS,"LesInventaires"); CmbInventaire.DataSource=DS.Tables["LesInventaires"]; CmbInventaire.DataTextField="Inventaire"; CmbInventaire.DataBind(); TxtBTitre.Text= DS.Tables["LesInventaires"].Rows[CmbInventaire.SelectedIndex]["Titre"].ToString(); TxtBEdition.Text= DS.Tables["LesInventaires"].Rows[CmbInventaire.SelectedIndex]["AnneEdition"].ToString(); cnn.Close(); } } void ClickSupprimer(object sender, EventArgs e) { string StrCnn = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source ="+MapPath("Biblio.mdb"); OleDbConnection cnn = new OleDbConnection(StrCnn); OleDbDataAdapter DA; DataSet DS; cnn.Open(); string StrSql = "DELETE FROM Ouvrage WHERE Inventaire = "+ CmbInventaire.SelectedValue; OleDbCommand cmd=new OleDbCommand(StrSql,cnn);
148
Karim Kalti
try { cmd.ExecuteNonQuery(); // Suppression DA = new OleDbDataAdapter("SELECT * FROM Ouvrage",cnn); DS = new DataSet(); DA.Fill(DS,"LesInventaires"); CmbInventaire.DataSource=DS.Tables["LesInventaires"]; CmbInventaire.DataTextField="Inventaire"; CmbInventaire.DataBind(); TxtBTitre.Text= DS.Tables["LesInventaires"].Rows[CmbInventaire.SelectedIndex]["Titre"].ToString(); TxtBEdition.Text= DS.Tables["LesInventaires"].Rows[CmbInventaire.SelectedIndex]["AnneEdition"].ToString(); } catch(Exception) { Response.Write("Erreur de suppression"); } finally { cnn.Close(); } } void Index_Changed(object sender, EventArgs e) { string StrCnn = "Provider = Microsoft.Jet.OLEDB.4.0; Data Source ="+MapPath("Biblio.mdb"); OleDbConnection cnn; OleDbDataReader rd; OleDbCommand cmd; cnn = new OleDbConnection(StrCnn); cnn.Open(); string StrSql = "SELECT * FROM Ouvrage WHERE Inventaire = "+CmbInventaire.SelectedValue; try { cmd = new OleDbCommand(StrSql,cnn); rd = cmd.ExecuteReader(); if(rd!=null) { if(rd.Read()) { TxtBTitre.Text=rd["Titre"].ToString(); TxtBEdition.Text=rd["AnneEdition"].ToString(); } } } catch(Exception) { Response.Write("erreur");} finally { cnn.Close();} } </script> <html> <head> </head> <body> <form runat="server"> <div align="left"><font size="6">Suppression d'ouvrages</font> </div> <div align="left"> </div> <div align="left"><asp:Label id="LbInventaire" runat="server">Inventaire : </asp:Label> <asp:DropDownList id="CmbInventaire" runat="server" Width="160px" OnSelectedIndexChanged="Index_Changed" AutoPostBack="True"></asp:DropDownList> <br/> <asp:Label id="LbTitre" runat="server">Titre : </asp:Label> <asp:TextBox id="TxtBTitre" runat="server" Width="161"></asp:TextBox> <br/> <asp:Label id="LbEdition" runat="server">Anne d'dition : </asp:Label> <asp:TextBox id="TxtBEdition" runat="server" Width="161"></asp:TextBox> </div> <div align="left"> </div> <div align="left"> <asp:Button id="BtnSupprimer" onclick="ClickSupprimer" runat="server" Width="86px" Text="Supprimer"></asp:Button> </div> </form> </body> </html>
149
Karim Kalti
Le code de l'exemple de suppression a t dlibrment crit de faon montrer la possibilit d'utiliser les modes connect et dconnect de ADO.NET dans ASP.NET. Ainsi dans certains gestionnaires on trouve parfois des accs la base l'aide des objets Command d'une part et l'aide du DataAdpeter et du DataSet d'autre part. Il serait plus judicieux d'utiliser un seul mode par gestionnaire. Il est noter par ailleurs que chaque gestionnaire a utilis ses propres objets de connexion la base. Il est possible d'optimiser encore plus le code en proposant une autre conception qui fait partager tous ces objets par les diffrents gestionnaires.
Exercices
Exercice d'application 1 : Proposer une version "code behind" des trois pages d'ajout, de suppression et de consultation d'ouvrages. Exercice d'application 2 : Proposer une nouvelle conception du code de la page de suppression d'ouvrages utilisant seulement un mode de travail (connect ou dconnect) et permettant de faire partager les objets de connexion la base par tous les gestionnaires. Exercice d'application 3 : Proposer une nouvelle conception du code de l'application (ajout, suppression et consultation d'ouvrages) de faon permettre le partage des mmes objets de connexion par toutes les pages de l'application.
150
Karim Kalti
Si un fichier Web.config est prsent dans le rpertoire racine d'un site, par exemple Inetpub\wwwroot , ses paramtres de configuration s'appliquent toutes les applications de ce site. Certains de ces paramtres peuvent tre redfinis l'intrieur d'une application et ce l'aide d'un fichier Web.config spcifique cette application et situ la racine de cette dernire. Remarque 1 : La prsence d'un fichier Web.config la racine d'une application ou dans un rpertoire donn est compltement facultative. Si aucun fichier Web.config n'est prsent, tous les paramtres de configuration du rpertoire sont automatiquement hrits du rpertoire parent.
151
Karim Kalti
Remarque 2 : ASP.NET configure IIS pour viter que le navigateur puisse accder directement aux fichiers Web.config afin de garantir que leurs valeurs ne risquent pas d'tre publiques. En cas de tentative d'accs ces fichiers, ASP.NET retourne l'erreur 403: Accs interdit.
Les groupes de sections : Le corps du fichier de configuration est organis d'une manire hirarchique en groupes de sections. Chaque groupe de sections est dfini par une balise qui porte le nom du groupe. Exemple : System.Web est un groupe de section qui contient les sections de configuration les plus frquemment utilises.
<configuration> <System.Web> <!- les paramtres de configurations doivent tre ici --> </System.Web> </configuration>
Un groupe de sections peut comporter d'autres sous-groupes de sections. Remarque : Les groupes de sections sont facultatifs. Ils ont essentiellement un intrt organisationnel permettant de regrouper les sections de configuration d'une manire thmatique. Section de configuration Une section de configuration est une zone qui comprend des paramtres de configuration. Cette zone est dfinie par une paire de balises qui porte le nom de la section. Les paramtres sont dfinis sous forme d'attributs de cette balise. Les sections de configuration les plus utilises dans le groupe de sections system.web sont : Section sessionState compilation trace Exemple :
<configuration> <System.Web> <SessionState> <!- les paramtres de configurations doivent tre ici --> </SessionState> <Compilation> <!- les paramtres de configurations doivent tre ici --> </Compilation> </System.Web> </configuration>
Description Permet de grer les sessions au sein de l'application Web. Permet de grer les paramtres de compilation pour ASP.NET. Permet de grer le suivi ASP.NET.
152
Karim Kalti
Centralisation de la configuration
Grce l'organisation hirarchique des fichiers de configuration et la possibilit d'hritage des paramtres, il est possible de centraliser tous les paramtres de toutes les applications Web dans un seul fichier Web.config plac la racine du serveur Web. L'accs aux paramtres spcifiques chaque application se fait alors l'aide d'une balise Location laquelle on passe le chemin de l'application comme suit :
<configuration> <location path="WebApp1"> <System.Web> <!- les sections de configuration de WebApp1 --> </System.Web> <location path="WebApp1"> <location path="WebApp2"> <System.Web> <!- les sections de configuration de WebApp2 --> </System.Web> <location path="WebApp2"> </configuration>
Si un utilisateur tente de substituer ces paramtres dans un autre fichier de configuration, le systme de configuration affiche une erreur :
<configuration> <system.web> <identity userName="developer" password="loginpw" /> </system.web> </configuration>
Paramtres personnaliss
Il est possible d'ajouter dans le fichier de configuration des paramtres personnaliss comme la chane de connexion une base de donnes par exemple. Les paramtres personnaliss sont placs dans une section de configuration spciale dfinie par la balise appSettings. Exemple :
<configuration> <appSettings> <add key="ConnectionString" value="c:\Data\..."/> <add key="Nom" value="Dupond"/> </appSettings> </configuration>
153
Karim Kalti
L'ajout d'un paramtre personnalis se fait l'aide de la balise <add> comme suit :
<add key="identificateur" value="valeur"/>
Type
Collection NameValueCollection
Signification
Permet de rcuprer la liste des paramtres dfinis dans la section appSettings sous forme d'une collection de paires (paramtre/valeur). La collection NameValueCollection possde un indexeur qui prend comme argument le nom du paramtre et qui retourne sa valeur.
Exemple :
using System.Configuration; . . . string strcnn =ConfigurationSettings.AppSettings["ConnectionString"];
154
Karim Kalti
155
Karim Kalti
Objectifs Accs rapide, intgr et gnralis l'information en interne (Intranet) ou en externe (Internet). Interoprabilit : Les services Web sont indpendants de la plateforme (unix, windows, ) et du langage de programmation (C#, VB.NET, Java, ). Leur capacit de faire converser entre elles des applications et des composants htrognes est remarquable. On peut trs bien raliser un service Web fonctionnant sous GNU/Linux en Java et l'interroger depuis une page Web ASP.NET en mme temps que depuis une application Perl. Rutilisation : l'utilisation des composants distribus permet d'acclrer le processus de dveloppement d'applications et rduit par consquent les cots. Exemples de services Web Diffusion d'informations : (horaires des vols, des trains, cours de la bourse, tats de stocks, incidents, ). Commerce lectronique : (prsentation, transactions, paiement, recherche, ) Authentification d'accs.
156
Karim Kalti
Remarque : la composition de services Un service Web peut jouer le rle de client un autre service Web. On parle dans ce cas de composition de services.
157
Karim Kalti
UDDI (standard) ou DISCO (MS) WSDL (bas sur XML et XSD) SOAP (bas sur XML)
Protocole de transport (http, SMTP, )
Publication et recherche de services Description des services Communication (change de messages) N'importe quel protocole (gnralement le HTTP)
Le niveau implmentation du service : cette description s'intresse aux informations permettant de localiser le service sur un serveur donn. Elle concerne : o Les ports : un port (appel galement endpoint) reprsente une adresse url qui est associe l'implmentation de l'une des liaisons d'un service par un fournisseur. Le service : Le service est dcrit comme une collection de ports. Chaque port dsigne l'adresse d'une des liaisons du service.
Remarque : Un mme service Web spcifi par son interface peut tre implmente par plusieurs fournisseurs. Les niveaux d'abstraction qu'offre le WSDL (notamment la distinction entre la description de l'interface et de l'implmentation) permettent de dcrire d'une manire unique un mme service et de rfrencer sparment ses diffrents fournisseurs (implmentations).
158
Karim Kalti
Elments d'un message SOAP Enveloppe : C'est l'enveloppe du message. Elle encapsule les sous lments du message. L'entte (header) : c'est sous lment optionnel de l'enveloppe. Il peut contenir des extensions d'informations telles que l'authentification, les sessions, Le corps (body) : c'est un sous lment obligatoire de l'enveloppe. Il contient des informations sur la mthode invoquer ainsi que ses paramtres (Request message) ou sur la valeur de retour (Response message). Il peut contenir un lment "Fault" en cas d'erreur.
159
Karim Kalti
Caractristiques de SOAP SOAP est bas sur le XML. Les donnes changes entre le demandeur et le fournisseur du service sont donc au format texte. SOAP est indpendant des systmes d'exploitation et des langages de programmation. Il permet par consquent l'interoprabilit des systmes. SOAP est indpendant du protocole de transport (il utilise souvent le protocole HTTP).
160
Karim Kalti
DISCO
DISCO (Discovery) est une technologie de Microsoft pour la publication et la recherche de services Web. Il s'agit d'un algorithme qui permet de rechercher les services Web exposs sur un serveur donn. Il permet galement de dcouvrir les capacits de chaque service et la manire d'interagir avec lui et ce en analysant le document WSDL qui accompagne ce service. Publication d'un service l'aide de DISCO Pour publier un service Web l'aide de DISCO, il suffit de crer un fichier .disco et de le placer dans le rpertoire racine du service Exemple : pour un service appel math, il faut ajouter le fichier .disco comme suit dans le rpertoire du service.
\inetpub \wwwroot \math (vroot) math.asmx web.config math.disco \bin simpleMath.dll complexMath.dll
Le fichier .disco est un document XML qui contient des liens aux ressources qui dcrivent le service (document WSDL).
<disco:discovery xmlns:disco="http://schemas.xmlsoap.org/disco/" xmlns:scl="http://schemas.xmlsoap.org/disco/scl/"> <!-- reference to other DISCO document --> <disco:discoveryRef ref="related-services/default.disco"/> <!-- reference to WSDL and documentation --> <scl:contractRef ref="math.asmx?wsdl" docRef="math.asmx"/> </disco:discovery>
Rcupration des informations l'aide de DISCO La rcupration des informations travers un fichier .disco se fait l'aide d'un utilitaire qui fonctionne en ligne de commande appel disco.exe. Cette commande prend comme argument l'url du fichier .disco du service consulter. Exemple :
c:\temp> disco.exe http://localhost/math/math.disco
Cette commande gnre en sortie un fichier appel result.discomap qui contient des informations sur le service Web situ cette url. Remarques : Il est possible d'utiliser au lieu des fichiers .disco, des fichiers .vsdisco pour rcuprer d'une manire dynamique la liste de tous les services Web qui se trouvent sur un serveur donn spcifi par son url. (c'est spcifique pour MS VS). DISCO est une technologie de microsoft. Elle utilise pour la publication et la recherche petite chelle. Le client doit connatre au pralable l'url du service Web qu'il veut consommer (ce n'est pas toujours le cas en pratique). L'alternative DISCO est UDDI qui est un standard universel pour la publication et la recherche grande chelle de services Web.
161
Karim Kalti
Organisation des donnes dans l'annuaire L'annuaire est organis sous forme de pages de trois catgories selon les informations qu'elles renferment : Les pages blanches : elles contiennent des informations qui concernent les entreprises (noms des entreprises, leurs coordonnes, leurs domaines d'activit, des descriptions supplmentaires, etc.). Les pages jaunes : Elles donnent la liste des services par catgorie selon leurs natures ou selon les entreprises qui les proposent. Les pages vertes : elles contiennent les spcifications techniques des services, classes par socit.
162
Karim Kalti
Exemples d'entit de donnes utilises par UDDI Le modle UDDI comporte cinq structures de donnes principales dcrites sous formes de schmas XML : BusinessEntity : Ensemble d'informations sur l'entreprise qui publie le service (domaine d'activit, nom, description, coordonnes). BusinessService : Ensemble d'informations sur le service publi par l'entreprise (nom du service, sa description, son code unique). tModel : ensemble d'informations dcrivant le modle du service. C'est l'interface qui dfinie la spcification du service (Description WSDL). BindingTemplate : ensemble d'informations concernant le lieu d'hbergement du service (url de ses points d'accs). Il s'agit de l'url de l'implmentation de la spcification dcrite dans le tModel. La spcification d'un service peut avoir plusieurs implmentations proposes par diffrents industriels sous forme de plusieurs BindingTemplate qui rfrencent donc le mme tModel. PublisherAssertion : ensembles d'informations ncessaires l'tablissement de contrats entre partenaires dans le cadre d'changes commerciaux.
163
Karim Kalti
Cette dclaration est faite dans un fichier (asmx). La directive @WebService indique que le fichier contient l'implmentation d'un service Web. L'attribut Language indique le langage de programmation utilis (C#, VB, JavaScript). L'attribut Class permet de spcifier le nom de la classe qui implmente le service Web.
164
Karim Kalti
NomDuService est le nom de la classe qui implmente le service Web. Cette classe publique comporte gnralement les mthodes qui seront exposes par le service. Mthodes exposes par un service Une mthode expose par un service est une mthode qui peut tre appele par le client du service. Une telle mthode : o doit tre membre de la classe qui implmente le service. o doit tre dclare publique. o doit tre prcde dans sa dfinition par l'attribut [WebMethod]. C'est cet attribut, qui va rendre la mthode appelables par les clients du service. Une mthode de la classe du service Web qui n'est pas dfinie en tant que [WebMethod] ne peut pas tre invoque par les clients mme si elle est dclare publique. [WebMethod] est un attribut prdfini en .NET dans l'espace de noms System.Web.Services. Ceci explique l'utilisation de la directive using System.Web.Services; avant la dfinition de la classe. Endroit de dfinition de la classe du service Web Dfinition dans le fichier (asmx) La classe qui implmente le service peut tre dfinie dans le fichier (asmx). Dans ce cas elle doit succder la dclaration du service.
<%@ WebService Language="C#" Class="NomDuService"%> using System.Web.Services; public class NomDuService { // Dfinition des mthodes du service [WebMethod] Mthode1( ) {} [WebMethod] MthodeN( ) {} }
Dfinition selon le modle "codebehind" La classe du service peut tre dfinie dans un fichier de code pur (.cs ou .vb) spar du fichier (asmx) selon le modle "codebehind" utilis par les WebForms (pages aspx). Contenu du fichier de dclaration du service (.asmx)
<%@ WebService Language="C#" CodeBehind="NomFichierClass.cs" Class="EspaceNoms.NomDuService"%>
La dclaration du service inclut dans ce cas une rfrence au fichier qui contient la dfinition de la classe. Cette rfrence est spcifie l'aide de l'attribut CodeBehind.
165
Karim Kalti
Remarque : Il est possible d'appeler dans la dclaration d'un service Web une classe dj compile au lieu du fichier contenant le code source de la classe. Dans ce cas, la dclaration du service doit tre effectue comme suit :
<%@ WebService Language="C#" Class="EspaceNoms.NomDuService, NomAssemblage"%>
NomAssemblage dsigne le nom de l'assemblage qui contient la classe compile. Ce dernier doit figurer dans le rpertoire \bin de l'application qui reprsente le service Web.
166
Karim Kalti
Remarque : Il est galement possible d'ajouter des informations supplmentaires pour chaque mthode du service et ce l'aide de la proprit Description de l'attribut [WebMethod].
[WebMethod (Description = "Cette mthode effectue ")] Mthode1( )
167
Karim Kalti
Le clic sur le lien vers la mthode Somme engendre l'affichage de la page suivante :
Cette page permet de tester la mthode Somme du service Web. L'appel de la mthode du service aurait pu tre effectu directement en tapant l'url suivante : http://localhost/Operations.asmx?op=Somme
168
Karim Kalti
Le navigateur affiche galement : o o le texte des deux messages SOAP utiliss par cette mthode pour recevoir les paramtres et pour renvoyer le rsultat. le texte montrant l'appel de la mthode l'aide de HTTP POST.
SOAP Le texte suivant est un exemple de demande et de rponse SOAP. Les espaces rservs affichs doivent tre remplacs par des valeurs relles. POST /Operations.asmx HTTP/1.1 Host: localhost Content-Type: text/xml; charset=utf-8 Content-Length: length SOAPAction: "www.Test.com/Somme" <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <Somme xmlns="www.Test.com"> <a>int</a> <b>int</b> </Somme> </soap:Body> </soap:Envelope> HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <SommeResponse xmlns="www.Test.com"> <SommeResult>int</SommeResult> </SommeResponse> </soap:Body> </soap:Envelope>
HTTP POST Le texte suivant est un exemple de demande et de rponse HTTP POST. Les espaces rservs affichs doivent tre remplacs par des valeurs relles. POST /Operations.asmx/Somme HTTP/1.1 Host: localhost Content-Type: application/x-www-form-urlencoded Content-Length: length a=string&b=string HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <int xmlns="
169
Karim Kalti
La saisie des valeurs pour les deux paramtres a et b et le clic sur le bouton Appeler engendre l'affichage de la page suivante qui contient le rsultat :
170
Karim Kalti
- <message name="SommeSoapIn"> <part name="parameters" element="s0:Somme" /> </message> - <message name="SommeSoapOut"> <part name="parameters" element="s0:SommeResponse" /> </message> - <portType name="OperationsSoap"> - <operation name="Somme"> <documentation>Cette mthode effectue la somme de deux entiers</documentation> <input message="s0:SommeSoapIn" /> <output message="s0:SommeSoapOut" /> </operation> </portType> - <binding name="OperationsSoap" type="s0:OperationsSoap"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document" /> - <operation name="Somme"> <soap:operation soapAction="www.Test.com/Somme" style="document" /> - <input> <soap:body use="literal" /> </input> - <output> <soap:body use="literal" /> </output> </operation> </binding> - <service name="Operations"> <documentation>Premier service Web</documentation> - <port name="OperationsSoap" binding="s0:OperationsSoap"> <soap:address location="http://localhost/Operations.asmx" /> </port> </service> </definitions>
171
Karim Kalti
Gnration de la classe proxy L'utilitaire WSDL prend comme argument l'url du service Web pour lequel on veut crer un proxy. Pour l'exemple prcdemment prsent il faut taper : WSDL http://localhost/Operations.asmx L'utilitaire gnre alors un fichier Operations.cs qui contient la dfinition du proxy.
//-----------------------------------------------------------------------------// <autogenerated> // This code was generated by a tool. // Runtime Version: 1.1.4322.573 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </autogenerated> //-----------------------------------------------------------------------------// // Ce // using using using using using using
code source a t automatiquement gnr par wsdl, Version=1.1.4322.573. System.Diagnostics; System.Xml.Serialization; System; System.Web.Services.Protocols; System.ComponentModel; System.Web.Services;
[System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="OperationsSoap", Namespace="www.Test.com")] public class Operations : System.Web.Services.Protocols.SoapHttpClientProtocol { public Operations() { this.Url = "http://localhost/operations.asmx"; } [System.Web.Services.Protocols.SoapDocumentMethodAttribute("www.Test.com/Somme", RequestNamespace="www.Test.com", ResponseNamespace="www.Test.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int Somme(int a, int b) { object[] results = this.Invoke("Somme", new object[] {a,b}); return ((int)(results[0])); }
172
Karim Kalti
public System.IAsyncResult BeginSomme(int a, int b, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("Somme", new object[] {a,b}, callback, asyncState); } public int EndSomme(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((int)(results[0])); } }
Le nom de la classe proxy est celui du service. Cette classe comprend trois mthodes pour chaque mthode expose du service : une pour l'appel directe (Somme) de la mthode du service et deux pour un appel asynchrone (BeginSomme et EndSomme). Pour pouvoir exploiter la classe proxy il suffit de l'ajouter au code de l'application cliente. Cette application en question peut reprsenter n'importe quelle application qui peut faire usage du protocole HTTP.
namespace ClientConsole { [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="OperationsSoap", Namespace="www.Test.com")] // La classe proxy public class Operations : System.Web.Services.Protocols.SoapHttpClientProtocol { public Operations() { this.Url = "http://localhost/operations.asmx"; } [System.Web.Services.Protocols.SoapDocumentMethodAttribute("www.Test.com/Somme", RequestNamespace="www.Test.com", ResponseNamespace="www.Test.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int Somme(int a, int b) { object[] results = this.Invoke("Somme", new object[] {a,b}); return ((int)(results[0])); } public System.IAsyncResult BeginSomme(int a, int b, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("Somme", new object[] {a,b}, callback, asyncState); } public int EndSomme(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((int)(results[0])); } }
173
Karim Kalti
// La classe qui fait appel au service class MainClass { public static void Main(string[] args) { // Instanciation du service Operations op=new Operations(); int i,j,s; Console.WriteLine("Donner un premier entier : "); i=Int32.Parse(Console.ReadLine()); Console.WriteLine("Donner un deuxime entier : "); j=Int32.Parse(Console.ReadLine()); // Appel de la mthode du service s= op.Somme(i,j); Console.WriteLine("La somme est : "+s); } } }
Le code de la classe proxy est plac dans un fichier appel Operations.cs. Le contenu de ce fichier est le suivant :
using using using using using using System.Diagnostics; System.Xml.Serialization; System; System.Web.Services.Protocols; System.ComponentModel; System.Web.Services;
174
Karim Kalti
public class Operations : System.Web.Services.Protocols.SoapHttpClientProtocol { public Operations() { this.Url = "http://localhost/operations.asmx"; } [System.Web.Services.Protocols.SoapDocumentMethodAttribute("www.Test.com/Somme", RequestNamespace="www.Test.com", ResponseNamespace="www.Test.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int Somme(int a, int b) { object[] results = this.Invoke("Somme", new object[] {a,b}); return ((int)(results[0])); } public System.IAsyncResult BeginSomme(int a, int b, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("Somme", new object[] {a,b}, callback, asyncState); } public int EndSomme(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((int)(results[0])); } }
Le code de l'interface qui utilise cette classe proxy pour faire appel au service Web se prsente comme suit :
<%@ Page Language="C#" Src="operations.cs" %> <script runat="server"> void Page_Load(object sender, EventArgs e) { if( IsPostBack == false) { TxtBE1.Text="0"; TxtBE2.Text="0"; } } void BtnSomme_Click(object sender, EventArgs e) { int i,j, Somme; if(TxtBE1.Text!="" && TxtBE2.Text!="") { Operations op = new Operations(); i= Int32.Parse(TxtBE1.Text); j= Int32.Parse(TxtBE2.Text); Somme = op.Somme(i,j); LbResultat.Text = "La somme est :" + Somme.ToString(); } } </script> <html> <head> </head> <body> <form runat="server"> <p> <asp:Label id="LbE1" runat="server">Entier 1 : </asp:Label> <asp:TextBox id="TxtBE1" runat="server"></asp:TextBox> <br /> <asp:Label id="LbE2" runat="server">Entier 2 : </asp:Label> <asp:TextBox id="TxtBE2" runat="server"></asp:TextBox> <br /> <asp:Button id="BtnSomme" onclick="BtnSomme_Click" runat="server" Text="Somme"></asp:Button> <br /> <asp:Label id="LbResultat" runat="server">La somme est : </asp:Label> </p> </form> </body> </html>
175
Karim Kalti
namespace ClientWinForm { [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="OperationsSoap", Namespace="www.Test.com")] // La classe proxy public class Operations : System.Web.Services.Protocols.SoapHttpClientProtocol { public Operations() { this.Url = "http://localhost/operations.asmx"; }
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("www.Test.com/Somme", RequestNamespace="www.Test.com", ResponseNamespace="www.Test.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int Somme(int a, int b) { object[] results = this.Invoke("Somme", new object[] {a,b}); return ((int)(results[0])); } public System.IAsyncResult BeginSomme(int a, int b, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("Somme", new object[] {a,b}, callback, asyncState); } public int EndSomme(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((int)(results[0])); } }
176
Karim Kalti
public class ClientWinForm : System.Windows.Forms.Form { private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox TxtBEntier1; private System.Windows.Forms.TextBox TxtBEntier2; private System.Windows.Forms.Label LbEntier2; private System.Windows.Forms.Button BtnSomme; private System.Windows.Forms.Label LbResultat; private System.ComponentModel.Container components = null; public ClientWinForm() { InitializeComponent(); } protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.TxtBEntier1 = new System.Windows.Forms.TextBox(); this.TxtBEntier2 = new System.Windows.Forms.TextBox(); this.LbEntier2 = new System.Windows.Forms.Label(); this.BtnSomme = new System.Windows.Forms.Button(); this.LbResultat = new System.Windows.Forms.Label(); this.SuspendLayout(); // label1 this.label1.Location = new System.Drawing.Point(16, 16); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(64, 16); this.label1.TabIndex = 0; this.label1.Text = "Entier 1 :"; // TxtBEntier1 this.TxtBEntier1.Location = new System.Drawing.Point(72, 16); this.TxtBEntier1.Name = "TxtBEntier1"; this.TxtBEntier1.TabIndex = 1; this.TxtBEntier1.Text = ""; // TxtBEntier2 this.TxtBEntier2.Location = new System.Drawing.Point(72, 40); this.TxtBEntier2.Name = "TxtBEntier2"; this.TxtBEntier2.TabIndex = 3; this.TxtBEntier2.Text = ""; // LbEntier2 this.LbEntier2.Location = new System.Drawing.Point(16, 40); this.LbEntier2.Name = "LbEntier2"; this.LbEntier2.Size = new System.Drawing.Size(64, 16); this.LbEntier2.TabIndex = 2; this.LbEntier2.Text = "Entier 2 :"; // BtnSomme this.BtnSomme.Location = new System.Drawing.Point(16, 64); this.BtnSomme.Name = "BtnSomme"; this.BtnSomme.TabIndex = 4; this.BtnSomme.Text = "Somme"; this.BtnSomme.Click += new System.EventHandler(this.BtnSomme_Click); // LbResultat this.LbResultat.Location = new System.Drawing.Point(16, 88); this.LbResultat.Name = "LbResultat"; this.LbResultat.TabIndex = 5; // ClientWinForm this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(224, 133); this.Controls.Add(this.LbResultat); this.Controls.Add(this.BtnSomme); this.Controls.Add(this.TxtBEntier2); this.Controls.Add(this.LbEntier2);
177
Karim Kalti
this.Controls.Add(this.TxtBEntier1); this.Controls.Add(this.label1); this.Name = "ClientWinForm"; this.Text = "ClientWinForm"; this.ResumeLayout(false); } [STAThread] static void Main() { Application.Run(new ClientWinForm()); } private void BtnSomme_Click(object sender, System.EventArgs e) { int i,j,s; // Instanciation de la classe du service Operations op = new Operations(); if(this.TxtBEntier1.Text!="" && this.TxtBEntier2.Text!="") { i=Int32.Parse(this.TxtBEntier1.Text); j=Int32.Parse(this.TxtBEntier2.Text); // Appel de la mthode du service s=op.Somme(i,j); this.LbResultat.Text="Le rsultat est : "+s.ToString(); } } } }
<%@ WebService Language="C#" Class="MathOps.Operations"%> using System.Web.Services; namespace MathOps { [WebService(Namespace = "www.Test.com", Description = "Premier service Web")] public class Operations { [WebMethod(Description = "Cette mthode effectue la somme de deux entiers")] public int Somme(int a, int b) { return a + b; } [WebMethod(Description = "Cette mthode effectue la division du premier paramtre par le second")] public int Division(int a, int b) { return a / b; } } }
178
Karim Kalti
La nouvelle classe proxy gnre par WSDL pour ce service se prsente comme suit :
// la classe proxy [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Web.Services.WebServiceBindingAttribute(Name="OperationsSoap", Namespace="www.Test.com")] public class Operations : System.Web.Services.Protocols.SoapHttpClientProtocol { public Operations() { this.Url = "http://localhost/operations.asmx";} [System.Web.Services.Protocols.SoapDocumentMethodAttribute("www.Test.com/Somme", RequestNamespace="www.Test.com", ResponseNamespace="www.Test.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int Somme(int a, int b) { object[] results = this.Invoke("Somme", new object[] { a, b}); return ((int)(results[0])); } public System.IAsyncResult BeginSomme(int a, int b, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("Somme", new object[] {a, b}, callback, asyncState); } public int EndSomme(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((int)(results[0])); } [System.Web.Services.Protocols.SoapDocumentMethodAttribute("www.Test.com/Division", RequestNamespace="www.Test.com", ResponseNamespace="www.Test.com", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] public int Division(int a, int b) { object[] results = this.Invoke("Division", new object[] {a, b}); return ((int)(results[0])); } public System.IAsyncResult BeginDivision(int a, int b, System.AsyncCallback callback, object asyncState) { return this.BeginInvoke("Division", new object[] { a, b}, callback, syncState); } public int EndDivision(System.IAsyncResult asyncResult) { object[] results = this.EndInvoke(asyncResult); return ((int)(results[0])); } }
Le test du service est effectu travers un client de type application Windows dont l'interface se prsente comme suit :
179
Karim Kalti
Une division par zro engendre l'affichage d'une bote de message indiquant l'occurrence d'une erreur.
Traitement de l'exception au niveau du serveur Il est galement possible de traiter l'erreur au niveau du serveur dans le service Web afin de modifier le message de l'exception. Le code suivant montre une nouvelle version de la mthode Division du service Web Operations qui traite l'exception leve par la division par zro.
[WebMethod(Description = "Cette mthode effectue la division du premier paramtre par le second")] public int Division(int a, int b) { try { return a / b; } catch (System.DivideByZeroException e) { throw new System.DivideByZeroException("Attention : La division par zro est interdite"); } }
La mthode Division du service Web lve une exception de type System.DivideByZeroException. Cette exception sera remonte par SOAP jusqu'au client mais toujours sous forme d'une exception de type SoapException.
180
Karim Kalti
Le code suivant montre une nouvelle version de la fonction de traitement de l'vnement clic du bouton Division qui traite l'exception et affiche le message d'erreur provenant du serveur.
private void BtnDivision_Click(object sender, System.EventArgs e) { try { int i,j,s; // Instanciation de la classe du service Operations op = new Operations(); i=Int32.Parse(this.TxtBEntier1.Text); j=Int32.Parse(this.TxtBEntier2.Text); // Appel de la mthode du service s=op.Division(i,j); this.LbResultat.Text="Le rsultat de la division est : "+s.ToString(); } catch(SoapException ex) { MessageBox.Show(ex.Message,"Erreur"); } }
Ceci est le message d'erreur affiche dans le cas d'une division par zro.
181
Karim Kalti
L'exemple suivant montre un appel asynchrone la mthode Somme dans le gestionnaire de l'vnement clic sur le bouton Ajouter dans le client de type application Windows.
// Ajout d'attributs la classe int s; Operations op; // Gestionnaire de l'vnement clic sur le bouton Somme private void BtnSomme_Click(object sender, System.EventArgs e) { int i,j,s; // Instanciation de la classe du service op = new Operations(); if(this.TxtBEntier1.Text!="" && this.TxtBEntier2.Text!="") { i=Int32.Parse(this.TxtBEntier1.Text); j=Int32.Parse(this.TxtBEntier2.Text); // Appel de la mthode du service op.BeginSomme(i,j, new AsyncCallback(FinSomme), null); this.LbResultat.Text="Le rsultat est : "+s.ToString(); } } // Fonction appele lorsque le service Web retourne sa valeur public void FinSomme(IAsyncResult ar) { if(ar.IsCompleted) s = (int)op.EndSomme(ar); op = null; }
La mthode BeginNomMthode (BeginSomme dans l'exemple courant) prend comme premiers arguments la liste des arguments de la mthode du service Web. L'avant dernier argument et un dlgu de type AsyncCallback qui est appel lorsque l'appel asynchrone est termin. Si cet argument prend comme valeur null alors aucun dlgu n'est appel. Le dernier argument de type object reprsente des informations supplmentaires fournies par l'appelant. La mthode BeginNomMthode renvoie une valeur de type IAsyncResult. Cette classe permet de donner l'tat de l'opration asynchrone notamment travers sa proprit IsCompleted.
182
Karim Kalti