Qual é a melhor solução alternativa para o cliente WCF `usando` problema de bloco?
Eu gosto de instanciar meus clientes de serviço WCF dentro de umusing
, pois é praticamente a maneira padrão de usar recursos que implementamIDisposable
:
using (var client = new SomeWCFServiceClient())
{
//Do something with the client
}
Mas, como observado emeste artigo da MSDN, agrupando um cliente WCF em umusing
bloco @ poderia mascarar quaisquer erros que resultassem no cliente sendo deixado em um estado com falha (como um tempo limite ou um problema de comunicação). Para encurtar a história, quando Dispose () é chamado, o método Close () do cliente é acionado, mas gera um erro porque está em um estado com falha. A exceção original é mascarada pela segunda exceção. Não é bom
A solução sugerida no artigo do MSDN é evitar completamente o uso de umusing
block e, em vez disso, instanciar seus clientes e usá-los da seguinte maneira:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
Comparado com ousing
bloco, acho isso feio. E muito código para escrever sempre que você precisar de um client
Felizmente, encontrei algumas outras soluções alternativas, como esta no IServiceOriented. Você começa com:
public delegate void UseServiceDelegate<T>(T proxy);
public static class Service<T>
{
public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>("");
public static void Use(UseServiceDelegate<T> codeBlock)
{
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}
Que permite:
Service<IOrderService>.Use(orderService =>
{
orderService.PlaceOrder(request);
});
Isso não é ruim, mas não acho que seja tão expressivo e facilmente compreensível quanto ousing
quadra
A solução alternativa que estou tentando usar foi a primeira vez que li sobre blog.davidbarret.net. Basicamente, você substitui o @ do clienDispose()
método onde quer que você o use. Algo como
public partial class SomeWCFServiceClient : IDisposable
{
void IDisposable.Dispose()
{
if (this.State == CommunicationState.Faulted)
{
this.Abort();
}
else
{
this.Close();
}
}
}
Isso parece permitir que ousing
bloqueie novamente sem o perigo de mascarar uma exceção de estado com falh
Então, existem outras dicas que eu tenho que olhar para usar essas soluções alternativas? Alguém sugeriu algo melhor?