Instancing ako jedno z nastavení správania WCF služieb špecifikuje spôsob vytvárania inštancií tried služby. Pozrime sa na dostupné možnosti a na spôsob ako ich implementovať.
reklama
Instancing ako jedno z nastavení správania WCF služieb špecifikuje spôsob vytvárania inštancií tried služby. Pozrime sa na dostupné možnosti a na spôsob ako ich implementovať.
Počas behu služby je vytvorená jedna alebo viacero inštancií implementačnej triedy ako odpoveď na správy. Implementačná trieda špecifikuje instancing mód, ktorý určuje ako sú vytvárané a zrušené tieto inštancie. WCF nám ponúka 3 módy vytvárania inštancií implementačnej triedy služby:
- per call - nová inštancia služby je vytvorená pre každú požiadavku klienta a potom je zrušená.
- per session - nová inštancia služby je vytvorená pre každé nové klientské session (vznik nového klientského kanála), inštancia je udržiavaná počas doby existencie session (treba použiť binding, ktoré podporuje session).
- single - jediná inštancia služby obsluhuje požiadavky od všetkých klientov počas celej doby behu aplikácie.
Výber konkrétneho módu záleží od toho aké sú naše požiadavky na uchovávanie stavových informácií (state management):
- per call - zvolíme ak nevyžadujeme uchovávanie stavu medzi volaniami jednotlivých operácii.
- per session - zvolíme ak požadujeme uchovávanie stavu pre každého klienta zvlášť.
- single - zvolíme ak chceme aby stav bol zdielaný medzi všetkými klientami a požiadavkami.
Vzájomná interakcia klienta a inštancie služby pri rôznych módoch instancing-u je znázornená na nasledujúcich obrázkoch:

Per call

Per session

Single
Príklad
Na príklade si ukážeme ako nastaviť rôzne módy instancing-u.
Services
Pre nastavenie troch rôznych módov instancing-u použijeme 3 služby, ktoré budú implementovať rozhranie ITestService obsahujúce 2 metódy. Spôsob instancing-u služby nastavíme pomocou atribútu [ServiceBehavior] a jeho vlastnosti InstanceContextMode.
Každá trieda predstavujúca službu vypíše vo svojom konštruktore a pri volaní metód informáciu na konzolu. Kód jednotlivých služieb v C# bude:
using System;
using System.ServiceModel;
using System.Runtime.Serialization;
namespace Services
{
[ServiceContract]
public interface ITestService
{
[OperationContract]
void Operation1();
[OperationContract]
void Operation2();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class Service1 : ITestService
{
public Service1()
{
Console.WriteLine("Service1.Service1()");
}
#region ITestService Members
public void Operation1()
{
Console.WriteLine("Service1.Operation1()");
}
public void Operation2()
{
Console.WriteLine("Service1.Operation2()");
}
#endregion
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class Service2 : ITestService
{
public Service2()
{
Console.WriteLine("Service2.Service2()");
}
#region ITestService Members
public void Operation1()
{
Console.WriteLine("Service2.Operation1()");
}
public void Operation2()
{
Console.WriteLine("Service2.Operation2()");
}
#endregion
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service3 : ITestService
{
public Service3()
{
Console.WriteLine("Service3.Service3()");
}
#region ITestService Members
public void Operation1()
{
Console.WriteLine("Service3.Operation1()");
}
public void Operation2()
{
Console.WriteLine("Service3.Operation2()");
}
#endregion
}
}
Host
Všetky tri služby budú hostované v jednej konzolovej aplikácii. Pre tri služby potrebujeme vytvoriť tri hostovacie prostredia pomocou inštancie triedy ServiceHost:
using System;
using System.ServiceModel;
using Services;
namespace Host
{
class Program
{
static void Main(string[] args)
{
ServiceHost host1 = new ServiceHost(typeof(Services.Service1));
ServiceHost host2 = new ServiceHost(typeof(Services.Service2));
ServiceHost host3 = new ServiceHost(typeof(Services.Service3));
host1.Open();
host2.Open();
host3.Open();
Console.ReadLine();
host1.Close();
host2.Close();
host3.Close();
}
}
}
Konfiguračný súbor hostovacej aplikácie bude obsahovať konfiguráciu endpointov jednotlivých služieb, nastavenie používania session a publikácie metadát:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="Services.Service1" behaviorConfiguration="MetadataSupport">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8001/" />
</baseAddresses>
</host>
<endpoint address="Service1"
binding="wsHttpBinding"
contract="Services.ITestService" />
</service>
<service name="Services.Service2" behaviorConfiguration="MetadataSupport">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8002/" />
</baseAddresses>
</host>
<endpoint address="Service2"
binding="wsHttpBinding"
contract="Services.ITestService" />
</service>
<service name="Services.Service3" behaviorConfiguration="MetadataSupport">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8003/" />
</baseAddresses>
</host>
<endpoint address="Service3"
binding="wsHttpBinding"
bindingConfiguration="BindingWithSession"
contract="Services.ITestService" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="BindingWithSession">
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MetadataSupport">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Klient
Klientská konzolová aplikácia pre testovacie účely bude volať operácie jednotlivých služieb. Táto aplikácia bude komunikovať so službami pomocou proxy tried, ktoré nám automaticky vygeneruje Visual Studio 2005 pomocou Add Service Reference. Zdrojový kód klientskej aplikácie v C# bude:
using System;
namespace Client
{
class Program
{
static void Main(string[] args)
{
using (Client.Service1.TestServiceClient client1 = new Client.Service1.TestServiceClient())
{
client1.Operation1();
client1.Operation2();
client1.Close();
}
using (Client.Service2.TestServiceClient client2 = new Client.Service2.TestServiceClient())
{
client2.Operation1();
client2.Operation2();
client2.Close();
}
using (Client.Service3.TestServiceClient client3 = new Client.Service3.TestServiceClient())
{
client3.Operation1();
client3.Operation2();
client3.Close();
}
Console.ReadLine();
}
}
}
V konfiguračnom súbore klientskej aplikácie nakonfigurujeme endpointy a nastavíme používanie session:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<client>
<endpoint address="http://localhost:8001/Service1"
binding="wsHttpBinding"
contract="Client.Service1.ITestService">
</endpoint>
<endpoint address="http://localhost:8002/Service2"
binding="wsHttpBinding"
contract="Client.Service2.ITestService">
</endpoint>
<endpoint address="http://localhost:8003/Service3"
binding="wsHttpBinding"
bindingConfiguration="BindingWithSession"
contract="Client.Service3.ITestService">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="BindingWithSession">
<reliableSession enabled="true" />
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
</configuration>
Po spustení hostovacej a klientskej aplikácie uvidíme v okne hostovacej aplikácie nasledovný výpis:

Na výpise môže byť pre niekoho prekvapujúci prvý riadok. Je to dané tým, že inštancia triedy Service2 je vytvorená hneď ako je vytvorené jej hostovacie prostredie (ServiceHost) pretože InstanceContextMode má hodnotu InstanceContextMode.Single.
Ostatné riadky sú myslím podľa očakávaní. Kompletný príklad si môžete stiahnúť tu.
Ing. Marián Košťál (csharp@azet.sk)