J'aime l'instanciation de mon service WCF clients au sein d'un using
bloc comme il est à peu près la norme de façon à utiliser les ressources qui implémentent IDisposable
:
using (var client = new SomeWCFServiceClient())
{
//Do something with the client
}
Mais, comme indiqué dans cet article MSDN, l'enveloppant d'un WCF client dans un using
bloc pourrait masquer les erreurs qui en résultent dans le client se retrouve dans une reproché à l'etat (comme un délai d'attente ou de problème de communication). Longue histoire courte, lorsque dispose() est appelée, la méthode Close() les feux, mais renvoie une erreur car il est dans un état faulted. L'exception d'origine est alors masqué par la deuxième exception. Pas bonne.
La solution de contournement proposée dans l'article MSDN est d'éviter complètement à l'aide d'un using
bloc, et au lieu d'instancier vos clients et de les utiliser quelque chose comme ceci:
try
{
...
client.Close();
}
catch (CommunicationException e)
{
...
client.Abort();
}
catch (TimeoutException e)
{
...
client.Abort();
}
catch (Exception e)
{
...
client.Abort();
throw;
}
Par rapport à l' using
bloc, je pense que c'est laid. Et beaucoup de code à écrire à chaque fois vous avez besoin d'un client.
Heureusement, j'ai trouvé quelques autres solutions, comme celle-ci sur IServiceOriented. Vous commencez avec:
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();
}
}
}
}
Ce qui permet alors:
Service<IOrderService>.Use(orderService =>
{
orderService.PlaceOrder(request);
});
Ce n'est pas mauvais, mais je ne pense pas que c'est expressive et facilement compréhensible que l' using
bloc.
La solution de contournement, je suis en train d'essayer de les utiliser j'ai lu à ce sujet sur blog.davidbarret.net. Fondamentalement, vous remplacez le client Dispose()
méthode partout où vous les utilisez. Quelque chose comme:
public partial class SomeWCFServiceClient : IDisposable
{
void IDisposable.Dispose()
{
if (this.State == CommunicationState.Faulted)
{
this.Abort();
}
else
{
this.Close();
}
}
}
Cela semble être en mesure de permettre à l' using
bloc de nouveau, sans le danger de masquage d'une reproché à l'état d'exception.
Donc, y at-il d'autres astuces que j'ai à regarder dehors pour l'utilisation de ces solutions de contournement? A quelqu'un de venir avec quelque chose de mieux?