Binding popisuje spôsob komunikácie endpointov WCF služieb. Pozrime sa bližšie na zložky z ktorých pozostáva binding, druhy bindings a vytváranie vlastných bindings.
reklama
Binding popisuje spôsob komunikácie endpointov WCF služieb. Pozrime sa bližšie na zložky z ktorých pozostáva binding, druhy bindings a vytváranie vlastných bindings.
Zložky tvoriace binding
Binding je tvorené nasledovnými zložkami:
- transport (TCP, Named Pipes, HTTP, MSMQ, ...),
- encoding (text, binary, ...),
- security,
- reliable session,
- transakcie (context flow).
Povinné zložky, ktoré musí obsahovať každé binding sú transport a encoding. Ostatné zložky sú nepovinné. Na zložky tvoriace binding sa môžeme pozerať ako na vrstvy, pričom konkrétne binding vytvoríme skladaním týchto vrstiev.
Ak sa nad týmto konceptom zamyslíme z pohľadu objektovo orientovaného programovania, tak je jasné, že všetky zložky tvoriace binding budú odvodené od nejakej spoločnej triedy. Tou triedou je abstraktná trieda BindingElement z menného priestoru System.ServiceModel.Channels. Od tejto triedy sú potom odvodené triedy reprezentujúce transport (TransportBindingElement), encoding (MessageEncodingBindingElement) a podobne. Týmto spôsobom je vytvorená hierarchia tried reprezentujúca zložky tvoriace binding. Časť tejto hierarchie tried znázorňuje nasledovný UML diagram:

System bindings
Priamo vo WCF máme k dispozícii bindings, ktoré označujeme ako systémové bindings. Ich prehľad spolu s ich vlastnosťami je v nasledovnej tabuľke:
| Binding |
Interoperability |
Security |
Session |
Transactions |
Duplex |
Encoding |
| BasicHttpBinding |
Basic Profile 1.1 |
Transport, Message, Mixed |
No |
No |
|
Text |
| WSHttpBinding |
WS |
Transport, Message, Mixed |
Transport, Reliable Session |
Yes |
|
Text |
| WSDualHttpBinding |
WS |
Message |
Reliable Session |
Yes |
Yes |
Text |
| WSFederationHttpBinding |
WS-Federation |
Message, Mixed |
Reliable Session |
Yes |
No |
Text |
| NetTcpBinding |
.NET |
Transport, Message, Mixed |
Reliable Session, Transport |
Yes |
Yes |
Binary |
| NetNamedPipeBinding |
.NET |
Transport |
Transport |
Yes |
Yes |
Binary |
| NetMsmqBinding |
.NET |
Message, Transport |
No |
Yes |
No |
|
| NetPeerTcpBinding |
Peer |
Transport |
No |
No |
Yes |
|
| MsmqIntegrationBinding |
MSMQ |
Transport |
No |
Yes |
|
|
BasicHttpBinding - pre komunikáciu webových služieb spĺňajúcich WS-Basic Profile.
WSHttpBinding - zabezpečené a interoperabilné binding bez podpory duplex kontraktov.
WSDualHttpBinding - zabezpečené a interoperabilné binding s podporou duplex kontraktov.
WSFederationHttpBinding - podpora protokolu WS-Federation.
NetTcpBinding - zabezpečené a optimalizované binding pre komunikáciu WCF aplikácii.
NetNamedPipeBinding - komunikácia WCF aplikácii v rámci jedného počítača.
NetMsmqBinding - komunikácia cez MSMQ.
NetPeerTcpBinding - viacpočítačová komunikácia.
MsmqIntegrationBinding - komunikácia medzi WCF aplikáciou a existujúcou MSMQ aplikáciou.
Binding môžeme k endpointu služby priradiť dvomi spôsobmi. Deklaratívne pomocou konfiguračného súboru napr.:
<endpoint address="http://localhost:8080/library"
binding="basicHttpBinding"
contract="Client.Library.ILibrary" />
alebo imperatívne pomocou kódu vytvoríme binding:
BasicHttpBinding binding = new BasicHttpBinding();
Custom bindings
Pokiaľ naše požiadavky nespĺňa ani jedno zo systémových bindings, môžeme si vytvoriť vlastné (custom) binding, ktoré bude spĺňať naše požiadavky. Vlastné binding si môžeme vytvoriť 3 spôsobmi:
- Vytvorením triedy odvodenej od triedy
System.ServiceModel.Channels.CustomBinding predstavujúcej kontajner, ktorý vyplníme požadovanými zložkami.
- Vytvorením triedy odvodenej od niektorej triedy reprezentujúcej systémové binding.
- Vytvorením triedy odvodenej od triedy
System.ServiceModel.Channels.Binding, čím získame úplnú kontrolu nad celou implementáciou.
Príklad
V príklade si ukážeme ako vytvoriť a použiť custom binding tretím spôsobom, teda odvodením (zdedením) od triedy System.ServiceModel.Channels.Binding.
Binding
Naše custom binding bude jednoduchá trieda, ktorú vytvoríme odvodením od abstraktnej triedy System.ServiceModel.Channels.Binding. V tejto novej triede musíme implementovať členy, ktoré sú v rodičovskej triede abstraktné. Je to metóda CreateBindingElements a vlastnosť Scheme. Custom binding bude pomenované SimpleHttpBinding a bude obsahovať iba dve zložky: transport (http) a encoding (text). Zložky binding-u v metóde CreateBindingElements dáme do kolekcie typu System.ServiceModel.Channels.BindingElementCollection a klonovanú kópiu kolekcie vrátime ako návratovú hodnotu metódy. Vrátená kolekcia by nikdy nemala obsahovať referencie na objekty definované vo vnútry triedy, a pri každom volaní metódy CreateBindingElements by mala byť vrátená nová inštancia kolekcie. To je dôvod použitia klonovania v tomto prípade.
V príklade je ukázaná iba minimálna implementácia custom binding-u, pre reálne použitie by bolo dobré doplniť tam funkcionalitu na spracovanie nastavení v konfiguračnom súbore. Zdrojový kód custom binding-u je:
using System;
using System.ServiceModel.Channels;
namespace Service
{
public class SimpleHttpBinding : Binding
{
private HttpTransportBindingElement transport;
private TextMessageEncodingBindingElement encoding;
public SimpleHttpBinding()
{
transport = new HttpTransportBindingElement();
encoding = new TextMessageEncodingBindingElement();
}
public override BindingElementCollection CreateBindingElements()
{
BindingElementCollection bindingElements = new BindingElementCollection();
bindingElements.Add(encoding);
bindingElements.Add(transport);
return bindingElements.Clone();
}
public override string Scheme
{
get { return transport.Scheme; }
}
//
// TODO: add configuration support
//
}
}
Servis
To, či vytvorené custom binding bude naozaj funkčné treba nejako vyskúšať. Vyskúšame to na jednoduchej službe, ktorá bude vraciať výsledky futbalových zápasov. Služba je jednoduchá, jej operácia vracia iba pole reťazcov. Zdrojový kód služby a rozhrania (resp. kontraktu), ktoré implementuje je:
using System;
using System.ServiceModel;
namespace Service
{
[ServiceContract]
public interface ILiveScore
{
[OperationContract]
string[] GetScores();
}
public class LiveScore : ILiveScore
{
#region ILiveScore Members
public string[] GetScores()
{
return new string[] {
"Celtic Glasgow - AC Milan 0:0",
"PSV Eindhoven - Arsenal 1:0",
"Lille - Manch. Utd 0:1",
"Real Madrid - Bayern Munchen 3:2"
};
}
#endregion
}
}
Host
Služba bude hostovaná v konzolovej aplikácii. Bude prístupná cez jeden endpoint, ktorého súčasťou bude binding typu SimpleHttpBinding:
using System;
using System.ServiceModel;
using System.ServiceModel.Description;
using Service;
namespace Host
{
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/livesportscore");
Type serviceType = typeof(Service.LiveScore);
Type contractType = typeof(Service.ILiveScore);
SimpleHttpBinding binding = new SimpleHttpBinding();
using (ServiceHost host = new ServiceHost(serviceType, baseAddress))
{
host.AddServiceEndpoint(contractType, binding, baseAddress);
host.Open();
Console.WriteLine("Service started at address: " + baseAddress);
Console.ReadLine();
host.Close();
}
}
}
}
Klient
Klientom služby bude konzolová aplikácia. V tomto prípade je prístup k službe realizovaný iným spôsobom ako bolo ukázané v minulých častiach seriálu. Nie je tu použitá automaticky vygenerovaná proxy trieda, ale namiesto toho je tu použitá generická trieda System.ServiceModel.ChannelFactory<TChannel>:
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using Service;
namespace Client
{
class Program
{
static void Main(string[] args)
{
EndpointAddress address = new EndpointAddress("http://localhost:8080/livesportscore");
SimpleHttpBinding binding = new SimpleHttpBinding();
ILiveScore proxy = ChannelFactory<ILiveScore>.CreateChannel(binding, address);
((IChannel)proxy).Open();
string[] scores = proxy.GetScores();
((IChannel)proxy).Close();
PrintScores(scores);
Console.ReadLine();
}
private static void PrintScores(string[] scores)
{
Console.WriteLine("Scores:\n");
foreach (string score in scores)
{
Console.WriteLine(score);
}
}
}
}
Zdrojový kód príkladu si môžete stiahnúť tu.
Ing. Marián Košťál (csharp@azet.sk)