Pokud voláme WCF službu pomoci vygenerovaného proxy clienta (např. přidáním service reference do svého projektu) a volání provádíme správně, tak zásadně nepoužíváme blok using resp. volání metody Dispose() na instanci naší client třídy. Důvody jsou hned dva a jsou docela dobře popsány např. zde na MSDN. Namísto toho jsme nuceni používat fragment podobný tomuto:
using System;
using System.ServiceModel;
//...
var client = new ServiceClient();
try
{
//Use client instance
//...
client.Close();
}
catch (CommunicationException e)
{
//...
client.Abort();
}
catch (TimeoutException e)
{
//...
client.Abort();
}
catch (Exception e)
{
//...
client.Abort();
throw;
}
Přestože toto již pravděpodobně funguje (pokud výjimky CommunicationException a TimeoutException ošetříme správně apod.), ale minimálně to není moc hezké a také pokud budeme mít ve své WCF službě metod vícero bude kód i poměrně dlouhý.
Lepším řešením by ale bylo vygenerovaného klienta nějak “opravit”, aby se dala jednotlivá volání pokud možno zjednodušit. A to je přesně to co lze a my teď uděláme. Využijeme toho, že klient je vygenerovaný jako partial třída a můžeme k ní tedy dopisovat vlastní kód a v tomto případě to bude naše vlastní implementace metody Dispose(). Do projektu tedy přidáme nový soubor, pojmenujeme ho podle názvu třídy našeho klienta (pro příklad výše to je ServiceClient.cs) a vložíme do něho tento kód:
using System;
using System.ServiceModel;
namespace ServiceClientProxy
{
public partial class ServiceClient : IDisposable
{
#region action methods
public void Dispose()
{
try
{
if (this.State != CommunicationState.Faulted &&
this.State != CommunicationState.Closed)
{
this.Close();
}
else
{
this.Abort();
}
}
catch (CommunicationException)
{
this.Abort();
}
catch (TimeoutException)
{
this.Abort();
}
catch (System.Exception)
{
this.Abort();
throw;
}
}
#endregion
}
}
(obecně zde stačí změnit namespace a jméno třídy clienta)
POZOR: Nezapomeňte u deklarace naší části partial třídy vždy uvést, že implementuje interface IDisposable, jinak nebude naše implementace metody Dispose použita a výsledkem bude chybný kód!
Volání WCF služby pak můžeme provádět již opět velmi elegantně takto:
using (var client = new ServiceClient())
{
//Use client instance
//...
}
(Pokud si budete chtít vyzkoušet, že se skutečně volá naše nová implementace metody Dispose(), budete potřebovat ve vygenerované třídě clienta zaremovat atribut [System.Diagnostics.DebuggerStepThroughAttribute()] v její deklaraci, aby šlo do této metody umístit breakpoint.)
A to je vše, na shledanou zas někdy příště.