.NET 3.0 en liten översikt - del 3
Förord
Vi fortsätter att utforska .NET 3.0 frameworket med genom en fallstudie på en chatt applikation. I denna artikel koncentrerar vi oss på klienten. Vi gör en WinForms klient, i senare artiklar återkommer vi med en WPF baserad klient.Innehåll
»»
»
»
»
»
Relaterade artiklar
» .NET 3.0 en liten översikt - del 1» .NET 3.0 en liten översikt - del 2
» .NET 3.0 en liten översikt - del 4 (WPF)
» .NET 3.0 en liten översikt - del 5 (WPF)
» .NET 3.0 en liten översikt - del 6 (WPF) - sista delen
I del 1 av artikelserien började vi med vårt chatt system och vi defineierade WCF gränssnittet för vår chatt service. I del två tittade vi på hur man kan implementera server funtionaliteten för chatten. I denna del är det följdaktligen dags för klienten.
Men va nu då, WinForms är ju inte 3.0 utan 2.0 tänker du kanske. Det stämmer, och i senare artiklar kommer det en WPF klient, men eftersom WPF är stort så gör vi först en WinForms klient som enbart fokuserar på WCF delarna. Behöver du lära dej WinForms så är inte detta rätt artikel.
När vi vill ansluta till en service kan vi göra på ett par olika sätt.
*Detta alternativ finns enbart ifall du har installerat Orcas community technical preview:en, och under ytan fungerar detta med största sannolikhet på samma sätt som alternativ ett
I detta fall använder vi oss av det tredje alternativet. För att konfigurera adressen och bindningen kan vi antingen använda oss av app.config som vi gjorde i servern, eller så kan vi åstadkomma samma sak programmatiskt. Vi ska se på båda varianterna.
Eftersom vi kör testar på samma maskin väljer vi att använda oss av named pipes, dual http bindingen finns också med kommenterad.
I koden använder vi oss sen av DualChannelFactory som följande:
Om vi vill använda oss av programmatisk konfiguration (t.ex. ifall vi vill låta användaren skriva in vilken server att ansluta till) så gör vi på följande sätt
För att få händelserna, dvs notifikationer från server till klient, att fungera så implementerar vi händelse gränssnittet i vår klass.
En viktig grej att komma ihåg är att också komma ihåg att dekorera klassen med CallbackBehavior attributet, för att indikera att "re-entranta" anrop är är tillåtna och att vi inte vill att WCF synkroniserar anropet till UI tråden. (Detta för att vi i annat fall förr eller senare kommer att råka ut för deadlock.)
Vi har nu skapat ett service gränssnitt och server, samt en WinForms klient för att komma igång. I nästa artikel börjar vi skapa en WPF klient.
En bild på testuppsättningen
Som vanligt, frågor och kommentarer mottages tacksamt!
Chatt klient 1 – WinForms
Men va nu då, WinForms är ju inte 3.0 utan 2.0 tänker du kanske. Det stämmer, och i senare artiklar kommer det en WPF klient, men eftersom WPF är stort så gör vi först en WinForms klient som enbart fokuserar på WCF delarna. Behöver du lära dej WinForms så är inte detta rätt artikel.
Ansluta till servicen
När vi vill ansluta till en service kan vi göra på ett par olika sätt.- Generera en proxy med hjälp av svcutil.exe
- Generera en proxy genom ”Add service reference..” i visual studio*
- Genom att använda (Dual)ChannelFactory
I detta fall använder vi oss av det tredje alternativet. För att konfigurera adressen och bindningen kan vi antingen använda oss av app.config som vi gjorde i servern, eller så kan vi åstadkomma samma sak programmatiskt. Vi ska se på båda varianterna.
Konfiguration via app.config
binding="netNamedPipeBinding" address="net.pipe://localhost/Chat"/>
Eftersom vi kör testar på samma maskin väljer vi att använda oss av named pipes, dual http bindingen finns också med kommenterad.
I koden använder vi oss sen av DualChannelFactory
DuplexChannelFactory m_factory = new DuplexChannelFactory(new InstanceContext(this), "ChatServer”);
IChat m_server = m_factory.CreateChannel(address);
Programmatisk konfiguration
Om vi vill använda oss av programmatisk konfiguration (t.ex. ifall vi vill låta användaren skriva in vilken server att ansluta till) så gör vi på följande sätt
NetNamedPipeBinding binding = new NetNamedPipeBinding();
EndpointAddress address = new EndpointAddress("net.pipe://localhost/Chat");
DuplexChannelFactory m_factory = new DuplexChannelFactory(new InstanceContext(this), binding);
IChat m_server = m_factory.CreateChannel(address);
För att få händelserna, dvs notifikationer från server till klient, att fungera så implementerar vi händelse gränssnittet i vår klass.
#region IChatEvents Members
public void MessageReceived(LemonDesign.Chat.Contract.Message message) {
if (InvokeRequired) {
txtOutput.Invoke((Action)MessageReceived, message);
} else {
txtOutput.Text = string.Format("{0}({1}): {2}{3}", message.Sender,
message.Timestamp.ToShortTimeString(), message.Content, Environment.NewLine) + txtOutput.Text;
}
}
public void ServerGoingDown() {
MessageBox.Show("Server going down");
}
#endregion
CallbackBehavior
En viktig grej att komma ihåg är att också komma ihåg att dekorera klassen med CallbackBehavior attributet, för att indikera att "re-entranta" anrop är är tillåtna och att vi inte vill att WCF synkroniserar anropet till UI tråden. (Detta för att vi i annat fall förr eller senare kommer att råka ut för deadlock.)
/// The callback behavior thing is important, otherwise we'll
/// end up with deadlock sooner or later
[CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
Sammanfattning
Vi har nu skapat ett service gränssnitt och server, samt en WinForms klient för att komma igång. I nästa artikel börjar vi skapa en WPF klient.En bild på testuppsättningen
Som vanligt, frågor och kommentarer mottages tacksamt!
Jonas Sevelin
Mer sånt tack