Quelle est la meilleure solution pour la WCF client à l'aide de " bloquer problème?

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 mettent en œuvre des 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 à la 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); 
}); 

C'est pas mal, mais je ne pense pas que c'est expressive et facilement compréhensible que la 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 la using bloc de nouveau, sans le danger de masquage d'une reproché à l'état d'exception.

Donc, existe-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?

  • Le dernier (qui inspecte cette.De l'état) est une course; elle ne pourrait pas être prise en défaut lorsque vous vérifiez le booléen, mais peut être prise en défaut lorsque vous appelez Close().
  • Vous lisez état; elle n'est pas prise en défaut. Avant de vous appeler Close(), le canal de défauts. Close() throws. Game over.
  • Le temps passe. Il peut être une très courte période de temps, mais techniquement, dans la période de temps entre la vérification de l'état du canal et de lui demander de fermer le canal de l'état peut changer.
  • Je suis allé avec la solution trouvée ici: omaralzabir.com/do-not-use-using-in-wcf-client Bon sujet, malheureux, mais je suis content qu'il était là quand j'en avais besoin...
  • Je voudrais utiliser Action<T> au lieu de UseServiceDelegate<T>. mineure.
  • Je n'aime vraiment pas cette assistance statique Service<T> car elle complique les tests unitaires (comme la plupart statique de choses à faire). Je préfère qu'il soit non-statique qui peut être injecté dans la classe qui l'utilise.
  • Être conscient de ne pas faire de gros contrats WCF, sinon le premier démarrage à froid à l'aide de la ChannelFactory va tuer votre performance sur le premier appel. Vous pouvez bien sûr le cache de l'usine, mais pour les développeurs, c'est un cauchemar à chaque fois pour avoir ce démarrage à froid sur chaque départ.
  • Juste couru à travers cela, mais n'ont pas enquêté sur: nuget.org/packages/ChannelAdam.Wcf
  • gros contrats WCF les bonnes pratiques et modèles ? l'intégralité du code source de l'échantillon à l'aide de Cache ChannelFactory à l'aide de P&P ? Références: comment-faire-appel-wcf-service correctement et comment faire facilement appel de la wcf service correctement et dzimchuk.net/post/wcf-error-helpers
  • meilleure solution est une comment-faire-appel-wcf-service correctement . La meilleure explication à ce sujet et contient l'intégralité du code source.

InformationsquelleAutor Eric King | 2009-02-21