Bonjour,

Différentes questions concernant les bons usages en WCF.

Mon contexte est le suivant :
- Une application cliente (WPF)
- Un ensemble de serveurs réunissant chacun différents services

Dans ce cadre, il peut arriver que l'un des serveurs ne soit pas disponible, la communication interrompue, etc.

Comme je dois accéder à une quinzaine de services avec chacun plusieurs méthodes, je me suis posé la question d'une gestion globale (unique) de ces erreurs de com. J'ai donc utilisé un proxy dont le code est fourni ci-après.

Tout ça fonctionne... seulement je n'arrive pas à trouver d'information pour savoir si je suis dans les bonnes pratiques WCF ou s'il existe d'autres solutions plus appropriées ?

Egalement, j'utilise des appels du type "_channelFactory.CreateChannel();" lors de chaque appel de service (j'ai sinon régulièrement des problèmes de timeout), mais est-ce la bonne façon de faire ?

Concernant les proxy, voici comment ça fonctionne :

- Mise en place du proxy pour un service donné :

Les services sont réunis dans une classe statique "Services".

Celle-ci dispose d'une fonction paramètre "CommunicationErrorHandler" permettant plus tard, en cas d'échec de l'appel au service d'afficher (par exemple) à l'utilisateur un message du type "La communication est interrompue. Cliquez sur OK pour réessayer. Cliquez sur Annuler pour quitter l'application".

Concernant le service lui même, je crée le ChannelFactory, puis le proxy et retourne son transparent proxy.

Au final, vu de l'extérieur, on effectue un appel normal de type "Services.AdminServices.MaMéthode(...)".

Voici le code (pour un des services) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
static class Services
{
        static Func<bool> _communicationErrorHandler;
        public static Func<bool> CommunicationErrorHandler { set { _communicationErrorHandler = value; } }
 
        static ServiceProxy<IAdminServices> _adminServicesProxy;
        public static IAdminServices AdminServices
        {
            get
            {
                if ( _adminServicesProxy == null )
                {
                    ChannelFactory<IAdminServices> channelFactory = new ChannelFactory<IAdminServices>( "AdminServices" );
 
                    _adminServicesProxy = new ServiceProxy<IAdminServices>( channelFactory, _communicationErrorHandler );
                }
 
                return (IAdminServices)_adminServicesProxy.GetTransparentProxy();
            }
        }
}
- La classe proxy :

Le constructeur prend en paramètre le ChannelFactory et la fonction "CommunicationErrorHandler".

Lors de l'invocation de la méthode, j'attrape les erreurs et retente l'Invoke tant que l'utilisateur le demande.

Seulement, je fais un "_instance = _channelFactory.CreateChannel();" lors de chaque appel pour éviter les timeout (inactivité).

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 
    class ServiceProxy<T> : RealProxy
    {
        T _instance;
        ChannelFactory<T> _channelFactory;
        Func<bool> _communicationErrorHandler;
 
        public ServiceProxy( ChannelFactory<T> channelFactory, Func<bool> communicationErrorHandler )
            : base( typeof( T ) )
        {
            _channelFactory = channelFactory;
            _channelFactory.Closed += new EventHandler( ChannelFactoryClosed );
            _channelFactory.Faulted += new EventHandler( ChannelFactoryFaulted );
 
            //_instance = _channelFactory.CreateChannel();
 
            _communicationErrorHandler = communicationErrorHandler;
        }
 
        void ChannelFactoryClosed( object sender, EventArgs e )
        {
        }
        void ChannelFactoryFaulted( object sender, EventArgs e )
        {
        }
 
        public override IMessage Invoke( IMessage msg )
        {
            try
            {
                _instance = _channelFactory.CreateChannel();
 
                IMessage result = RemotingServices.GetRealProxy( _instance ).Invoke( msg );
 
                if ( result is ReturnMessage )
                {
                    ReturnMessage returnMessage = (ReturnMessage)result;
 
                    if ( returnMessage.Exception != null )
                        throw returnMessage.Exception;
                }
 
                return result;
            }
            catch ( Exception e )
            {
                if ( MyCommunicationException.ExitConfirm == false )
                {
                    if ( _communicationErrorHandler != null && _communicationErrorHandler() )
                        return Invoke( msg );
                }
 
                throw new MyCommunicationException( e );
            }
        }
    }
Est-il possible de faire différemment (plus efficace, plus dans les normes ou bonnes pratiques) ?

Merci de vos critiques !