Professional Documents
Culture Documents
C# I WCF
C# I WCF
C# i .Net Framework
.NET Framework je dizajniran kao integrisano okruenje razvoj aplikacija za Internet, desktop Windows Forms aplikacije, kao i za mobilne ureaje (pomou Compact Framework).Osnovne ideje pri dizajniranju su bile:
Da se formira konzistentno objektno orijentisano okruenje za razliite aplikacije. Da se napravi okruenje koje minimizuje probleme za uvoenjem novih verzija programa ("DLL Hell") koji su postojali u Windows (COM) okruenju, i da se pojednostavi proces distribucije/instalacije. Da se formira portabilno okruenje, bazirano na opteprihvaenim standardima, koje moe da se izvrava na proizvoljnom operativnom sistemu. Da se obezbedi upravljano (managed) okruenje u kome e se kod lako i sigurno izvravati.
Da bi se ostvarili ovi ciljevi, .NET Framework je oslonjen na arhitekturu koja deli framework ba dva dele: Common Language Runtime (CLR) i Framework Class Library (FCL). Slika 1. prikazuje tu podelu. CLR vodi rauna o izvravanju koda i svim ostalim zadacima u vezi sa tim: kompajliranje, upravljanje memorijom, sigurnost, upravljanje nitima, i kontrolie tipove podataka. Kod koji se izvrava u CLR se naziva upravljani (managed) kod. Nasuprot tome, neupravljni (unmanaged) je kod koji ne implementira zahteve za rad u .Net framework-u kao to je COM ili Windows API . Druga komponenta, Framework Class Library, predstavlja biblioteku klasa i struktura koje su na raspolaganju aplikacijama koje rade u .NET. Tu spadaju klase za pristup bazama podataka, grafiki intefejs, interoperabilnost sa neupravljanim kodom, sigurnost podataka, kao i za Web i Windows forme. Svi programski jezici prilagoeni .NET-u koriste ovu bibilioteku. Slika 1. Osnovne komponente .Net Framework-a
Konsturkcija C# Programa
Na slici 3 su prikazani osnovni elementi C# programa Slika 3. Osnovni elementi C# programa
Kod sa slike 3. se sastoji od klase MyApp koja poseduje programsku logiku i klasu Apparel koja sadri podatke. U programu se formira instanca Apparel i dodeljuje se promenivoj myApparel. Ovaj program se dalje koristi da bi se ispisala vrednost promenjive FabType i Price na ekran. Bitni delovi ovog programa su: 1. using naredba definie supove klasa (namespace) System. U ovom programu se koriste samo osnovni namespace System u kome se nalaze osnovni tipovi podataka. using naredba govori prevodiocu gde da gleda kada trai koriene tipove podataka, ime je omogueno da nije potrebno pisati puno ime klase. Naprimer, mogue je samo napisati Label umesto System.Web.UI.WebControls.Label. 2. Sva programska logika i podaci moraju biti ubaeni u: klase, strukture, enumeracije, intefejse ili delegate. Za razliku od Visual Basic-a, C# nema globalne promenjive koje bi postojale van navedenih tipova podataka. Pristup tipovima i njihovim podacima je striktno kontrolisano. U navedenom primeru public omoguuje da druge klase kao to je MyApppristupe lanicama Apparel klase. 3. Main() method je obavezan za svaku izvrnu C# aplikaciju. Ovaj metod slui kao ulazna taka za aplikaciju; ona uvek mora biti static i slovo M mora biti veliko. Mogue je definisane i verzije Main()koje imaju ulazne parametre i/ili povratne vrednosti.
FCL typovi
System.Object System.String System.Decimal System.Boolean System.Char System.Byte System.SByte System.Int16 System.Int32 System.Int64 System.UInt16 System.UInt32 System.UIint64
Description Osnovna klasa za sve dugi tipovi. Sekvenca Unicode karaktera. Precizan decimalni broj sa 28 cifara. Vrenosti true ili false. 16-bit Unicode karakter. 8-bit neoznaeni celobrojni tip. 8-bit oznaeni celobrojni tip. 16-bit oznaeni celobrojni tip. 32-bit oznaeni celobrojni tip. 64-bit oznaeni celobrojni tip. 16-bit neoznaeni celobrojni tip. 32-bit neoznaeni celobrojni tip. 64-bit neoznaeni celobrojni tip. Jenostruka preciznost sa pokretnim zarezom. Dvostruka preciznost sa pokretnim zarezom.
Primer
if (bmi < 24.9) { weight = "normal"; riskFactor = 2; } else { weight = "over"; riskFactor=6; }
switch (expression) { case constant expression: // statements; // break/goto/return() case constant expression: // statements; // break/goto/return() default: // statements; // break/goto/return() }
switch (ndx) { case 1: fabric = "cotton"; blend = "100%"; break; case 2: // combine 2 & 3 case 3: fabric = "cotton"; blend = "60%"; break; default: // optional fabric = "cotton"; blend = "50%"; break; }
Petlje
U C# postoje etiri vrste petlji: while, do, for, i foreach, koje takoe imaju slinu strukturu kao i u Javi ili C++. U tabeli 2. su prikazani definicije i primeri ovih naredbi. Deifnicija
while ( boolean expression ) { body }
Primer
byte[] r = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF}; int ndx=0; int totVal = 0; while (ndx <=6) { totVal += r[ndx]; ndx += 1; } byte[] r = {0x00, 0x12, 0x34, 0x56, 0xAA, 0x55, 0xFF}; int ndx=0; int totVal = 0; do { totVal += r[ndx]; ndx += 1; }while (ndx <= 6); int[] r = {80, 88, 90, 72, 68, 94, 83}; int totVal = 0; for (int ndx = 0; ndx <= 6; ndx++) { totVal += r[ndx]; } int totVal = 0; foreach (int arrayVal in r) { totVal += arrayVal; }
for ( [initialization]; [termination condition]; [iteration] ) { for-body } foreach ( type identifier in collection ) { body }
Klase u C#
Definicija klase u C# ima sledee elemente: 1. Atributi su opcionalni elementi koji dodatno opisuju klasu (recimo ClassDesc, Serialiazable) 2. U Deklaraciji klase se definisu prava pristupa kao i ime klase 3. U klasi je mogue definisati lokalne konstante i osobine 4. Konstruktor slui za inicijalizaciju klase. Moe postojati vie konstruktora sa razliitim ulaznim parametrima, ali konstruktor nikada ne vraa vrednost. 5. Momou Property-a se mogu kontrolisati prava pristupa osobinama klase 6. Metode predstavljaju funkcije koje se mogu pozvati nad objetkom klase
Slika 4. Elementi klase u C#
Interfejsi Interfejsi predstavljaju skup metoda koje neka klasa treba da implementira. Interfejs se definie pomou kljune rei interface
[attributes] [modifiers] interface {interface body} [;] identifier [:baselist]
Generics Generics, predstavlja novi concept uveden u.NET 2.0, i nudi eleganto reenje koje eliminie kastvovanje tipa, proveru tipa, i pakovanje (boxing) koje se koristi kada se pritivni tipovi prebacuju u object.
Kolekcije u .Net-u
U .NET-u, kolekcija je zajedniko ime za skup klasa koje predstavljaju klasine structure podataka koje se koriste za grupisanje srodnih podataka. Tu spadaju stacks, queue, hash table, array, i dictionary. Sve one su definisane u dva namespace-a: System.Collections i System.Collections.Generic. u .NET verzijama 1.0 i 1.1, postoji samo System.Collections. Sa pojavom .NET 2.0, originalne kolekcije su promenjene tako da podravaju generics. Tabele 3. Interfejsi za kolekcije Interface Opis
ICollection
Osnovni interfejs za sve klase. Sadri osobinu Count koja govori koliko ima elementa u kolekciji.Takoe poseduje metodu za kopiranje kolekcije u niz (CopyTo). Definie metodu koja slui za poreenje dva elementa u kolekciji (CompareTo) to je kljuno za sortiranje kolekcije. Omoguuje da se objekti predstavljaju u obliku key -value parova. Omoguuje prolazak kroz kolekciju koja definie IDictionary tako to omoguuje prolaz kroz klueve i vrednsoti Definie metode za jednostavnu iteraciju kroz kolekiciju. Pomou iteratora je mogue jedino oitavanje elemenata kolekcije. Tu spadaju metode
GetEnumerator, Current, MoveNext, Reset
IComparer
IDictionary IDictionaryEnumerator
IEnumerator IEnumerable
IHashCodeProvider IList
Osnovni interfejs za sve list. Kontrolie da li elementi liste mogu izmenjeni, dodati, ili obrisani
Po tome koje interfejse podrzavaju mogu se razlikovati tri podrvste kolekcija sto je prikazano na slici 5
Slika 5. Kolekcije u C#
Sa uvodjenjem Generics u .Net formirane su i odgovarajue kolekcije, a njihov uporedni spisak je dat u tabeli 4 Tabela 4. Uporeni prikaz kolekcija sa i bez generics klasa System.Collections System.Collections.Generic
Comparer Hashtable ArrayList Queue SortedList Stack ICollection IComparable IComparer IDictionary IEnumerable IEnumerator IKeyComparer IList Comparer<T> Dictionary<K,T> List<T> Queue<T> SortedDictionary<K,T> Stack<T> ICollection<T> IComparable<T> IComparer<T> IDictionary<K,T> IEnumerable<T> IEnumerator<T> IKeyComparer<T> IList<T> LinkedList<T>
(not applicable)
ZADATAK: Formirati ArrayList i u njega ubaciti million promenjivih tipa int, zatim formirati List<int> i u nju ubaciti isti broj elemenata. Uporediti vremena izvravanja ova dva postupka.
ArrayList a1 = new ArrayList(); Stopwatch stop = new Stopwatch(); stop.Start(); Trace.WriteLine(stop.ElapsedMilliseconds.ToString()); int max = 10000000; for (int i = 0; i < max; i++) a1.Add(i); Trace.WriteLine(stop.ElapsedMilliseconds.ToString()); List<int> a2 = new List<int>(); for (int i = 0; i < max; i++) a2.Add(i); Trace.WriteLine(stop.ElapsedMilliseconds.ToString());
Delegati i Dogaaji
Klik na dugme, pokretanje mia preko forme, pritisak na Enter dugme, karakter primljen sa I/O portasve su ovo okidai (trigger) koji obino pozivaju jedan ili vie poziva programskih rutinama za obradu dogaaja. U .NET svetu dogaaji su lanice klase isto kao i osobine i metode. Sve klase iz .Net Framework biblioteke klasa imaju dogaaje. Osnovni primer je Control klasa, koja slui kao osnovna klasa za sve GUI komponente. Ova klasa ima dogaajeClick, DoubleClick, KeyUp, i GotFocus koji su dizajnirani da prepoznaju najee akcije koje se dogaaju u interakciji korisnikog interfejsa i programa. Sad duge strane je potrebno definisati metode koje su odgovorne da odreaguju na dogaaje. Ove metode se zovu obraivai dogaaja (event hander). Slika 6. Odnos izmeu dogaaja i obraivaa dogaaja
Delegati
Delegati povezuju dogaaje i obraivae dogaaja. Ovaj objekat odrava listu metoda koje treba pozvati kada se desi dogaaj. C# kompajler vri proveru da bi obezbedio da delegat poziva samo metode koje imaju ulazne parameter i povratne vrednosti koje su specificirane u opisu delegata.Kao primer moemo pogedati delegate koji im sledeu definiciju: public delegate void AlarmUProcesu (int type, string msg); Kada se delegat definie, C# kompajler pravi sealed klasu koja ima ime kao i delegat (AlarmUProcesu). U klasi je definisan konstuktor koji prima parameter ime metode. Ta klasa sadri metode koje omoguuju delegatu da odrava listu metoda koju treba pozvati. Metoda mora biti registrovan kod delegate da bi ga delegat pozvao. Samo metode koje nemaju povratnu vrednost i primaju dva parametra (int i string) mogu biti registrovane kod delegata; u suprotnom e biti prijavljena greska pri prevoenju. Listing 1. prikazuje kako se definie AlarmUProcesu delegat i kako se registuje vie metoda za njega. Kada neko pozove delegata, on proe
kroz svoju internu listu za pozive, i pozove regisrovane metode redosledom kojim su registrovani. .
{ Console.WriteLine("Alarm odstampan-tip:"+ t.ToString()+ " sa porukom: "+s ); } public static void DodajAlarmULog(int t, string s) { // dodati kod za upis u bazu Console.WriteLine("Alarm upisan u bazu:" + t.ToString()+" sa porukom: "+ s); } public static void Main() { AlarmUProcesu myDel; // register method to be called by delegate myDel = new AlarmUProcesu(OdstamajAlarm); // register second method myDel += new AlarmUProcesu(DodajAlarmULog); // call delegate myDel(1, "Kvar na motoru 1 u pogonu 2"); } }
Treba primetiti da se operator += koristi za dodavanje metode u listu pozivanja. Nasuprot tome metod moe biti izbrisan iz te liste pomou operatora -=
myDel += new AlarmUProcesu (OdstamajAlarm); // dodaje metod u listu myDel -= new AlarmUProcesu (OdstamajAlarm); // uklanja metod iz liste
ZADATAK: Formirati klasu Item koja ima tri osobine: Value tipa double, TimeStamp tipa DateTime i Quality tipa int. Zatim formirati klasu Server koja sadri mapu Dictionary<int,Value> u koju se smetaju vrednosti nekih veliina. Server treba da ima dve metode Write koja ima dva ulazna parametra id veliine i Item, i metodu Read koja ima ulaznu vrednost int, a vraa Item.
public class Item { public double Value; public DateTime TimeStamp; public int Quality; public Item(double v, DateTime t, int q) { Value = v; TimeStamp = t; Quality = q; } }; public class Server { private Dictionary<int, Item> items = new Dictionary<int, Item>(); public void Write(int id, Item item) { items[id] = item; } public Item Read(int id) { return items[id]; } }; static void Main(){ { Server s = new Server();
s.Write(1, new Item(1.2, DateTime.Now, 1)); s.Write(2, new Item(4.4, DateTime.Now, 0)); int id = 1; Item i = s.Read(id); Console.WriteLine(@"Vrednost ocitana: id = {0}, Vrednost = {1}, vreme = {2}, kvalitet ={3} ", id, i.Value, i.TimeStamp, i.Quality); }
Dodatni zadaci: 1. Proiriti program tako da server podrava motodu Clear koja brie sve veliine iz mape 2. Uvesti proveru da li ima elemenata u mapi pri pozivu metode Read
WCF Service
WCF Service se sastoji iz tri dela Servis koja implemntira metode koje e biti pozivane, host u kom e se servis izvravati, i jednu ili vie taaka pristupa (endpoints) na koje e se klijenti povezivati. Sva komunikacija u WCF-u se deava kroz take pristupa. U taki pristupa je definisan ugovor (Contract) koji definie metode servisa kojima klijent moe pristupati. Druga bitna stvar koja se defiie je nain povezivanja (binding) koji specificira tip komunikacionog kanala koji e biti korien. Trei deo endpint-a je adresa na kojoj e servis biti postavljen
Ugovor
Zatim je potrebno definisati ugovor (contract) IWCFServer koji ima dve operacije: Write koji upisuje double vrednost u promenjivu definisanu sa id-om. Druga funkcija, Read oitava vrednost veliine sa datim id-om.
// File: ServerWCF.cs [ServiceContract] public interface IWCFServer { [OperationContract] void Write(int id, doulbe input); [OperationContract] doulbe Write(int id); }
U navedenom primeru je definisano da e servis biti dosutpan pomou HTTP transportnog protokola na adresi http://localhost:8000/IServiceWCF
return value; } } [ServiceContract] public interface IWCFServer { [OperationContract] void Write(int id, double input); [OperationContract] double Read(int id); }
[ServiceContract] public interface IWCFServer { [OperationContract] void Write(int id, double input); [OperationContract] double Read(int id); }
sa:
WSHttpBinding binding = new WSHttpBinding();
Proveriti kakvav format poruke e biti prikazan u serverskoj aplikaciji posle poziva Write metode u ovom sluaju.
Sledei korak je da se definie Binding za endpoint za metapodakte, zatim se formira metapodatke, i na kraju se endpoint doda u ServiceHost.
// instantiate a ServiceHost, passing the type to instantiate // when the application receives a message ServiceHost svc = new ServiceHost(typeof(HelloWCF)); // BEGIN NEW METADATA CODE // create a ServiceMetadataBehavior ServiceMetadataBehavior metadata = new ServiceMetadataBehavior(); // add it to the servicehost description svc.Description.Behaviors.Add(metadata); // create a TCP metadata binding Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding(); // create an address to listen on WS-Metadata exchange traffic
URI za
Uri mexAddress = new Uri("net.tcp://localhost:5000/IHelloWCF/Mex"); // add the metadata endpoint svc.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexAddress); // END METADATA CODE
Svcutil.exe e napraviti: WCFServer.cs i output.config. Kada se pogleda WCFServer.cs moe se videti da je napravljen izvorni kod za IWCFServer inteface, intefejs IWCFServerChannel i tip WCFServerClient. Moe se primetiti da u WCFServer.cs nema podatka o adresi servera. Ta informacija se nalazi u drugoj datoteci generisanoj pomou svcutil.exe (output.config). Da bi pokazali kako se koriste generisane datoteke formiraemo novog konzolnog klijenta za WCFServer (WCFSender). Prvo je potrebno preimenovati output.config datoteku tako da postane config za novog klijenta (proneni output.config u app.config).
using System; using System.ServiceModel; sealed class WCFSender { static void Main(){ // print to the console that we are sending a message Console.WriteLine("Pocetak pozivanja service-a"); // create the WCFServerClient type created by svcutil WCFServerClient proxy = new WCFServerClient(); // invoke the Say method proxy.Write(2, 11.22); proxy.Close(); // print to the console that we have sent a message Console.WriteLine("Poruka poslana serveru "); Console.ReadLine(); } }
Pokrenuti WCFServer klijentsku aplikaciju i proveriti da li vrednost mogue oitati iz drugog klijenta ZADACI ZA SAMOSTALAN RAD: 1. Promeniti WCFServer tako da podrava vie ServiceEndpoint-a 2. Proveriti performase komunicije Pomou (slati veliki broj poruka)
[AttributeUsage(AttributeTargets.Method)] public sealed class OperationContractAttribute : Attribute { public bool IsOneWay {get;set;} } IsOneWay IsOneWay
ima podrazumevanu vrednost = false, to znai da operacija nije jednosmerna. Ako se postavi na True ta operacija postaje jednosmerna:
Zadatak: proiriti postojei interface IWCFServer sa dodatnom meodom StartBackupData koja je jednosmerna. Zatim u implementaciji servera dodati tu metodu tako da u njoj server eka (pomou Thread.Sleep metode) 5 sekundi kako bi simulirao operaciju koja dugo traje (recimo pisanje na disk velike koliine podataka) i proveriti da li je klijent blokiran za vreme izvravanja operacije na serveru.
public interface IWCFServer { //ovo je dodatna metoda potrebno je sacuvati postojece [OperationContract(IsOneWay = true)] void StartBackupData(string path); } sealed class WCFServer : IWCFServer { //ovo je dodatna metoda potrebno je sacuvati postojece public void StartBackupData(string path) { System.Threading.Thread.Sleep(5000); } }