2010-11-23 41 views
2

J'essaye de trouver une manière élégante de réessayer une opération quand un canal de WCF est dans l'état défectueux. J'ai essayé d'utiliser Policy Injection AB pour reconnecter et réessayer l'opération lorsqu'une exception d'état défectueux se produit lors du premier appel, mais la méthode PolicyInjection.Wrap ne semble pas aimer l'encapsulation des objets TransparentProxy (proxy renvoyé par ChannelFactory.CreateChannel).Réessayer mécanisme sur l'appel d'opération WCF lorsque le canal dans l'état jugéled

Y at-il un autre mécanisme que je pourrais essayer ou comment pourrais-je essayer de faire fonctionner la solution de PIAB correctement - tous les liens, exemples, etc. seraient grandement appréciés.

Voici le code que j'utilisais qui périclite:
var channelFactory = new ChannelFactory(endpointConfigurationName);
var proxy = channelFactory.CreateChannel(...);
proxy = PolicyInjection.Wrap<IService>(proxy);

Merci.

Répondre

0

Merci beaucoup pour votre réponse. Ce que j'ai fini par faire était de créer une classe de type décorateur qui a implémenté l'interface de mon service, qui a ensuite simplement enveloppé le proxy transparent généré par ChannelFactory. J'ai ensuite pu utiliser le bloc Application Injection Policy pour créer une couche qui injecterait du code dans chaque appel d'opération qui tenterait l'opération, et si une exception CommunicationObjectFaultedException se produisait, le canal serait abandonné, recréé et réessayé. . Cela fonctionne bien maintenant - même si cela fonctionne très bien, le seul inconvénient est que la classe wrapper a dû implémenter toutes les opérations de service, mais c'était la seule façon d'utiliser le PIAB car cela avait du sens pour moi au cas où je trouverais un à l'avenir, il était assez facile de changer simplement en utilisant des interfaces.

3

Je préfère utiliser les fonctions de rappel, quelque chose comme ceci:

private SomeServiceClient proxy; 

    //This method invokes a service method and recreates the proxy if it's in a faulted state 
    private void TryInvoke(Action<SomeServiceClient> action) 
    { 
     try 
     { 
      action(this.proxy); 
     } 
     catch (FaultException fe) 
     { 
      if (proxy.State == CommunicationState.Faulted) 
      { 
       this.proxy.Abort(); 
       this.proxy = new SomeServiceClient(); 
       //Probably, there is a better way than recursion 
       TryInvoke(action); 
      } 
     } 
    } 

    //Any real method 
    private void Connect(Action<UserModel> callback) 
    { 
     TryInvoke(sc => callback(sc.Connect())); 
    } 

Et dans votre code, vous devez appeler

ServiceProxy.Instance.Connect(user => MessageBox.Show(user.Name)); 

au lieu de

var user = ServiceProxy.Instance.Connect(); 
MessageBox.Show(user.Name); 

Bien que mon code utilise proxy -classe approche, vous pouvez écrire un code similaire avec les canaux.

+0

Merci pour votre réponse - c'est très apprécié. Mon seul souci avec cette solution est que je devrais, pour les appels de service impairs 100-200 que j'ai, s'assurer que chaque invocation d'un appel de service est ensuite enveloppé dans un ServiceProxy.Instance.TryInvoke, et d'ajouter à cela, un cauchemar de maintenance assurant que tous les appels de service supplémentaires sont également enveloppés - Je ne vois pas d'autre moyen de contourner cela que d'utiliser Policy Injection AppBlock (ou autre framework de type AOP) - à moins que je ne manque quelque chose. – CraigM