You are on page 1of 22

DISTRIBUIRANI UPRAVLJAKI SISTEMI

Osnove C# jezika i WCF-a


-SKRIPTA-












Novi Sad
Decembar, 2008
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







Common Language Runtime
Common Language Runtime upravlja celim ivotnim vekom aplikacije: on pronalazi kod, prevodi ga,
uitava potrebne klase, upravlja njihovim izvravanjem, i osigurava automatsko oslobaanje memorije.
CLR je zaduen i za integraciju koda izmeu razliitih programskih jezika.
Prevoenje .NET Code
Programski prevodioci koji su kompatiblini sa CLR-on proizvode kod koji je pogodan za izvravanje u
runtime-u, za razliku od onih proizvedenih za specifini CPU. Ovaj kod, poznat pod razliitim
imenima Common Intermediate Language (CIL), Intermediate Language (IL), ili Microsoft
Intermediate Language (MSIL), je asemblerski jezik koji se pakuje u EXE ili DLL datoteke.
Ovaj kod (intermediate code) je kljuna stvar za ispunjenje osnovnog cilja .NET Framework-a
ineroperabilnost izmeu programskih jezika.Slika 2 ilustruje na koji nain Common Language
Runtime nemora da zna, niti treba da zna, u kom programskom jeziku je aplikacija napisana. CLR
komunicija sa jeziki nezavisnim IL. Zahvaljujui tome to aplikacije komuniciraju kroz IL, izlaz iz
jednog prevodioca moe moe biti integrisano sa kodom koji je proizveo drugaiji prevodilac.
Slika 2. Mesto i funkcija CLR-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.
Tipovi podataka i kontrola toka programa
Osnovni tipovi podataka (primitives), kao to im i samo ime kae, predstavljaju jezgro C# tipova
podataka. Slue kao gradivni blokovi za kompleksnije tipove klasa i struktura. Promenjive ovog tipa
sadre jednu vrednost i uvek imaju istu predefinisanu veliinu..U tabeli 1. je data lista osnovnih tipova
podatak, odgovarajui FLC tipovi podataka, i veliine memorije koju zauzimaju.
Tabela 1. Osnovni tipovi podata
C# tipovi FCL typovi Description
object System.Object
Osnovna klasa za sve dugi tipovi.
string System.String
Sekvenca Unicode karaktera.
decimal System.Decimal
Precizan decimalni broj sa 28 cifara.
bool System.Boolean
Vrenosti true ili false.
char System.Char
16-bit Unicode karakter.
byte System.Byte
8-bit neoznaeni celobrojni tip.
sbyte System.SByte
8-bit oznaeni celobrojni tip.
short System.Int16
16-bit oznaeni celobrojni tip.
int System.Int32
32-bit oznaeni celobrojni tip.
long System.Int64
64-bit oznaeni celobrojni tip.
ushort System.UInt16
16-bit neoznaeni celobrojni tip.
uint System.UInt32
32-bit neoznaeni celobrojni tip.
ulong System.UIint64
64-bit neoznaeni celobrojni tip.
single (float) System.Single
Jenostruka preciznost sa pokretnim zarezom.
double System.Double
Dvostruka preciznost sa pokretnim zarezom.

Kontrola toka programa
Kontrola programa u C# je vrlo slina kontroli programa u Javi ili C++. Tabela 2. prikazuje definiciju i
primere za uslovno grananje i case sturturu.
Tabela 1. Kontrola toka programa
Uslovne komande Primer
if (boolean expression) {
// statements
} else {
// statements
}
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 Primer
while
( boolean expression )
{ body }
byte[] r = {0x00, 0x12, 0x34, 0x56,
0xAA, 0x55, 0xFF};
int ndx=0;
int totVal = 0;
while (ndx <=6)
{
totVal += r[ndx];
ndx += 1;
}
do { do-body }
while (
boolean expression );

byte[] r = {0x00, 0x12, 0x34, 0x56,
0xAA, 0x55, 0xFF};
int ndx=0;
int totVal = 0;
do
{
totVal += r[ndx];
ndx += 1;
}while (ndx <= 6);
for ( [initialization];
[termination condition];
[iteration] )
{ for-body }
int[] r = {80, 88, 90, 72, 68, 94, 83};
int totVal = 0;
for (int ndx = 0; ndx <= 6; ndx++) {
totVal += r[ndx];
}
foreach ( type identifier in collection
) { body }
int totVal = 0;
foreach (int arrayVal in r)
{
totVal += arrayVal;
}

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 identifier [:baselist]
{interface body} [;]
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).
IComparer
Definie metodu koja slui za poreenje dva elementa u kolekciji
(CompareTo) to je kljuno za sortiranje kolekcije.
IDictionary
Omoguuje da se objekti predstavljaju u obliku key -value parova.
IDictionaryEnumerator
Omoguuje prolazak kroz kolekciju koja definie IDictionary tako to
omoguuje prolaz kroz klueve i vrednsoti

IEnumerator

IEnumerable


Definie metode za jednostavnu iteraciju kroz kolekiciju. Pomou iteratora
je mogue jedino oitavanje elemenata kolekcije. Tu spadaju metode
GetEnumerator, Current, MoveNext, Reset
IHashCodeProvider
Definie hashCode za svaki objekak u kolekciji. Poseduje jednu methodu:
GetHashCode(object obj)
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 Comparer<T>
Hashtable Dictionary<K,T>
ArrayList List<T>
Queue Queue<T>
SortedList SortedDictionary<K,T>
Stack Stack<T>
ICollection ICollection<T>
IComparable IComparable<T>
IComparer IComparer<T>
IDictionary IDictionary<K,T>
IEnumerable IEnumerable<T>
IEnumerator IEnumerator<T>
IKeyComparer IKeyComparer<T>
IList IList<T>
(not applicable)
LinkedList<T>

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.
.
Listing 1. Deklaracija delegate i poziv dogaaja

// file: delegate.cs
using System;
using System.Threading;
class DelegateSample
{
public delegate void AlarmUProcesu(int type, string msg);
public static void OdstamajAlarm(int t, string s)
{
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
Windows Communication Foundation

Windows Communication Foundation, ili WCF, je programsko okruenje (deo .Net Framework-a)
koje slui za meuprocesnu komunikaciju. Originalno je ovaj projekat bio poznat po imenu "Indigo", a
predstavlja jedan od etiri novih API-a koji su uvideni u .Net 3.0 koji su objavljeni Decembra 2006.
Ideja WCF-a je da ujedini razliite komunikacijone programske modele koji su postojale u .NET 2.0, u
jedinstven model. .NET 2.0 je posedovao razliite API-e za SOAP-baziranu komunikaciju (Web
servise), binarni API za komunikaciju izmeu aplikacija koje su pokrenuti na Windows plaftormama
(.Net Remoting), transakcionu komunikaciju (Distributed Transactions), i asinhrone komunikacije
(Message Queue).
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
Tabela 5.Tipovi povezivanja u WCF-u
BasicHttpBinding - Osnovni HTTP nain kominikacije koji obezbeuje maksimalnu
interoperabilnost, a zasnovan je na WS-BasicProfile 1.1
WSHttpBinding napredniji HTTP zasnovan na WS-* protocols
WSDualHttpBinding - Dupleks HTTP komunikacija, server otvara dugi kanal kroz koji moe
pozivati metode na klijentu.
WSFederationBinding - HTTP komunikacija u kojoj se pristup podacima moe biti
kontrolisan preko prava pristupa koje dodeljuje specifian odgan za dodelu sertifikata
NetTcpBinding Sigurana, pouzdana, komuikacija visokih performansi zasnovana na TCP
protokolu i binarnim porkukama.
NetNamedPipeBinding Sigurna, pouzdana, komunikacija visokih performansi izmeu WCF
aplikacija koje su pokrenute na istom raunaru
NetMsmqBinding Komunikacija izmeu WCF aplikacija kojas se zasniva na Microsoft Message
Queuing (MSMQ) serveru
MsmqIntegrationBinding - Komunikacija izmeu WCF aplikacija i ostalih aplikacija preko
MSMQ
NetPeerTcpBinding Komunikacija izmeu WCF aplikacija preko Windows Peer-to-Peer
mrea.
Sinhrona komunikacija pomou WCF-a (Veba 2)
U narednom primeru bie opisan nain pravljenja command promt klijenta i servera. U VS 2008
okruenju izabrati File-> New project, pa u otvorenom dijalogu Visual C# i za tip projekta Console
Application. Prvo se formira klasa ServerWCF.
// File: ServerWCF.cs
using System;

sealed class ServerWCF {
static void Main(){

}
}
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);
}
Definisanje Adrese i naina povezivanja (Binding)
Posle definisanja ugovora potrebno je rei gde server treba da slua dolazece poruke i u kom formatu
e te poruke doi. Za to slue adresa System.Uri tipa, i nain povezivanja
System.ServiceModel.Channels.Binding ili neki drugi izvedeni tip.
// File: ServerWCF.cs
static void Main(){
// definise gde ce servis slusati
Uri address = new Uri("http://localhost:8000/IServiceWCF");

// definisanje nacina povezivanja
BasicHttpBinding binding = new BasicHttpBinding();
}
U navedenom primeru je definisano da e servis biti dosutpan pomou HTTP transportnog protokola
na adresi http://localhost:8000/IServiceWCF

Formairanje take pristupa (Endpoint)
Sledee sto je potrebno formirati je taka pristupa (Endpoint) ona se satoji od: adrese, binding-a, i
contract -a. Svaki WCF moe da ima vie endpoint-a. Klasa System.ServiceModel.ServiceHost slui
za pravljenje taaka pristupa i takoe uva sve napravljene endpoint-e i omoguuje pristup serveru.
Sledei primer formira taku pristupa za ServerWCF i otvara ga za sluanje na portu 4000, zatim
obavetava korisnika da je server podignut i eka na pritisak na tastaturu za zavretak programa.
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

sealed class WCFServer : IWCFServer {
// indicate when a WCFServer object is created
WCFServer() { Console.WriteLine("WCFServer object created"); }

static void Main(){
// define where to listen for messages
Uri address = new Uri("http://localhost:4000/IWCFServer");
// define how to exchange messages
BasicHttpBinding binding = new BasicHttpBinding();
// instantiate a ServiceHost, passing the type to instantiate
// when the application receives a message
ServiceHost svc = new ServiceHost(typeof(WCFServer));
// add an endpoint, passing the address, binding, and contract
svc.AddServiceEndpoint(typeof(IWCFServer), binding, address);
// begin listening
svc.Open();
// indicate that the receiving application is ready and
// keep the application from exiting immediately
Console.WriteLine("WCFServer spreman za prinanje poruka");
// wait for incoming messages
Console.ReadLine();
// close the service host
svc.Close();
}
static Hashtable items = new Hashtable();

// received messages are dispatched to this instance
// method as per the service contract
public void Write(int id, double input)
{
items[id] = input;
Console.WriteLine("Vrednost upisana {0} = {1} the body contains: {0}",
id.ToString(), input.ToString());
}
public double Read(int id)
{
double value = -1;
if (items.ContainsKey(id))
{
Console.WriteLine("Vrednost ocitana {0} = {1} the body contains:
{0}", id.ToString(), value.ToString());
value = (double)items[id];
}
return value;
}

}
[ServiceContract]
public interface IWCFServer {
[OperationContract]
void Write(int id, double input);
[OperationContract]
double Read(int id);
}
WCF klijentska aplikacija
Sa klijentske strane su isti gradivni elementi potrebni kako bi se ostvarila komunikacija sa serverom:
address, binding, i contract i oni se formiraju na slian nain kao i na servrskoj strani. Klijentsku
aplikaciju formirati kao novu konzolnu applikaciju.
// File: HelloWCFApp.cs
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;

sealed class ClientWCF
{
// indicate when a ClientWCF object is created
ClientWCF() { Console.WriteLine("ClientWCF object created"); }
static void Main()
{
// define where to listen for messages
Uri address = new Uri("http://localhost:4000/IWCFServer");
// define how to exchange messages
BasicHttpBinding binding = new BasicHttpBinding();

// begin the sender code
// create a channelFactory<T> with binding and address
ChannelFactory<IWCFServer> factory =
new ChannelFactory<IWCFServer>(binding,
new EndpointAddress(address));
// use the factory to create a proxy
IWCFServer proxy = factory.CreateChannel();
// use the proxy to send a message to the receiver
int id = 1; double writeValue = 100.4; double readValue;
proxy.Write(id, writeValue);
Console.WriteLine("Vrednost upisana {0} = {1}", id.ToString(),
writeValue.ToString());
readValue = proxy.Read(id);
Console.WriteLine("Vrednost ocitana {0} = {1}", id.ToString(),
readValue.ToString());
Console.ReadLine();

}

}

[ServiceContract]
public interface IWCFServer
{
[OperationContract]
void Write(int id, double input);
[OperationContract]
double Read(int id);
}
Analiza formata poruke (Message)
WCF omoguuje lako oitavanje sadraja poruke koja je razmenjena izmedju klijenta i servera. To se
ini pomou klase OperationContext.Current.RequestContext.RequestMessage, tako da sada Write
metoda izgleda ovako:
public void Write(int id, double input)
{
items[id] = input;
Console.WriteLine("Vrednost upisana {0} = {1}", id.ToString(),
input.ToString());

Console.WriteLine(OperationContext.Current.RequestContext.RequestMessage.ToString(
));
}
Sada izlaz serverske aplikacije po pozivu Write metode izgleda:
WCFServer spreman za prinanje poruka
WCFServer object created
Vrednost upisana 1 = 100.4
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addr
essing/none">http://localhost:4000/IWCFServer</To>
<Action s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/
addressing/none">http://tempuri.org/IWCFServer/Write</Action>
</s:Header>
<s:Body>
<Write xmlns="http://tempuri.org/">
<id>1</id>
<input>100.4</input>
</Write>
</s:Body>
</s:Envelope>
WCFServer object created
Vrednost ocitana 1 = 100.4
Mala promena sa velikim posledicama
WCF infrastruktura je zaduena za ceo proces razmene poruka, zato je promena formata poruka veoma
jednostavna iz perspektive programera. Ako samo promenimo jedan red i u klijentu i u serveru koji
definise nain povezivanja. Razmenjene poruke e imati potpuno drugaiji format. Recimo
zameniemo:
BasicHttpBinding binding = new BasicHttpBinding();
sa:
WSHttpBinding binding = new WSHttpBinding();
Proveriti kakvav format poruke e biti prikazan u serverskoj aplikaciji posle poziva Write metode u
ovom sluaju.
Upotreba metapodataka (Metadata)
U prvom primeru smo krenuli od injenice da i server i klijent poznaju Contract IWCFServer. Mada
ovo u optem sluaju nije nemogue uvodi ogranienje da se i klijenti moraju menjati svaki put kada
se desi minimalna promena Contract-a.
WS-MetadataExchange specifikacija opisuje kako server moe da objavi format podataka koji se
razmenjuje. Po default-u WCF ne objavljuje metapodatke. Ako je potrebno mogue je formirati
endpoint koji slui specifino za razmenu metapodataka.
Prvi korak za pravljenje endpoint-a za metapodatke je da se izmeni ServiceHost tako da prua
metapodake. To se radi tako to se objekta System.ServiceModel.
Description.ServiceMetadataBehavior doda u behavior kolekciju u ServiceHost. Behavior je
specifina informacija koju WCF koristi da izmeni procesiranje lokalnih poruka. Sledei primer
prikazuje kako se dodaje ServiceMetadataBehavior objekat u aktivni ServiceHost:
// instantiate a ServiceHost, passing the type to instantiate
// when the application receives a message
ServiceHost svc = new ServiceHost(typeof(WCFServer), address);

// BEGIN NEW METADATA CODE
// create a ServiceMetadataBehavior
ServiceMetadataBehavior metadata = new ServiceMetadataBehavior();
metadata.HttpGetEnabled = true;
// add it to the servicehost description
svc.Description.Behaviors.Add(metadata);
Sledei korak je da se definie Binding za endpoint za metapodakte, zatim se formira URI za
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 mexAddress = new Uri("net.tcp://localhost:5000/IHelloWCF/Mex");
// add the metadata endpoint
svc.AddServiceEndpoint(typeof(IMetadataExchange),
mexBinding,
mexAddress);
// END METADATA CODE
Klijentska aplikacija sa Metapodacima
Microsoft .NET Framework SDK instalira i program svcutil.exe, koji moe da pita pokrenutu
aplikaciju za poruke koje razmenjuje i na osnovu toga generie proxy. svcutil.exe koristi WS-
MetadataExchange protokol, kao i WSDL get semantiku.
Generisanje Proxy sa Svcutil.exe
Pre nego to se pokrene svcutil.exe, treba proveriti da je WCFServer.exe pokrenut. Nakon toga se
pokrene Windows SDK Command Prompt i pokrene sledea komanda:
C:\temp>svcutil /target:code net.tcp://localhost:5000/IWCFServer/Mex
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).
Izvorni kod za WCFSender with Svcutil.exe-Generated Types
Prvo je potrebno napraviti novi projekat (Console Application) po imenu WCFSender. U projekat
ubaciti app.config I WCFServer.cs dobijene od svcutil.exe






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)

Jednosmerne metode (Veba 3)
Kada operacija nema povratnu vrednost, i kada klijentu nije vano da li je poziv uspeo ili nije mogu se
koristiti One-Way operacije. Kada klijent uputi poziv WCF generie upit (request), ali se odgovarajui
odgovor nee nikada generisati. Bitno je napomenuti da eventuali izuzetci (exception) koji se dogode
na serveru nee stii do klijenta. U idealnom sluaju kada klijent pozove one-way metodu, on treba da
bude blokiran samo kratko vreme potrebno da se uputi poziv. U stvarnosti, one-way nisu isto to i
asinhroni pozivi. Kada one-way pozivi stignu do servisa, mozda nee biti obraeni odmah, mogu biti
stavljeni u red ekanja na strani servisa. Koliko poruka (bili one-way ili request-reply) the servis moe
da ubaci u red ekanja zavisi od konfiguraciji kanala. Ako broj poruka u redu ekanja prevazilazi
kapacitet reda, klijent e biti blokiran, iako je u pitanju one-way poziv. Sa druge strane, ako je poziv
primljen bez reda ekanja (to je najei sluaj), klijent je osloboen i moe da nastavi sa
izvravanjem, dok servis procesira poziv u pozadini. Svi WCF binding podravaju one-way operacije.
Konfigurisanje jednosmerni operacija
OperationContract atribut ima Boolean IsOneWay:
[AttributeUsage(AttributeTargets.Method)]
public sealed class OperationContractAttribute : Attribute
{
public bool IsOneWay
{get;set;}
}
IsOneWay ima podrazumevanu vrednost = false, to znai da operacija nije jednosmerna. Ako se
IsOneWay postavi na True ta operacija postaje jednosmerna:
[ServiceContract]
interface IMyContract
{
[OperationContract(IsOneWay = true)]
void MyMethod( );
}

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);
}
}

You might also like