Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Unity et WCF

Je rebondis sur le billet de Thomas à propos de WCF et de la résolution du proxy WCF par Unity (ou tout autre conteneur).

Prenons cet exemple basique de service:

  
    [ServiceContract]
    public interface ICalc
    {
        [OperationContract]
        int Add(int a, int b);


        [OperationContract]
        int Div(int a, int b);
    }

Dans cet exemple une division par zéro va produire une exception qui aurait du être géré par un FaultContract au niveau de l’opération. La conséquence est fatale pour le proxy client: le “channel” passe en état “Faulted” et plus aucune opération est possible. Si on laisse le soin à une bibliothèque tierce de créer le proxy, si la stratégie de création est le singleton, on est bloqué à la première erreur coté serveur.

Alors comment savoir si le “channel” est dans le bon état?On ne le peut pas si on n’a que l’interface du contrat comme lien avec le proxy comme dans l’exemple de Thomas. On a alors généralement 2 solutions:

  • Le proxy fournit une propriété Channel
  • Si l’on ne passe pas par le proxy, on peut passer par une interface un peu plus évoluée que l’interface contrat.

L’interface suivante est crée par le générateur de proxy de Visual Studio (mais on aurait pu l’écrire directement):

  
    public interface ICalcChannel : Client_ConfByConfig.CalcSvc.ICalc, System.ServiceModel.IClientChannel {
    }

Il suffit ensuite de créer un ChannelFactory<ICalcChannel> et nous avons un proxy créé avec nos méthodes et l’accès au “Channel” via l’interface “IClientChannel”.

Dans ce cas, c’est la factory de WCF qui va faire le boulot pour nous: donc  plus de classe cliente. Pour utiliser cela avec Unity, nous allons utiliser un LifetimeManager. Nous allons donner à une classe intermédiaire la responsabilité de créer le proxy pour nous.

Et pour WCF cela peut ressembler à cela:

  
    internal class WCFLifetimemanager<t> : LifetimeManager, IDisposable where T : IDisposable
    {
        ChannelFactory _factory;
        
        
        public WCFLifetimemanager()
            : this("*")
        {

        }

        public WCFLifetimemanager(string endpoint)
        {
            _factory = new ChannelFactory<t>(endpoint);
        }

        public override object GetValue()
        {
            var ret =  _factory.CreateChannel();

            return ret;
        }

        public override void RemoveValue()
        {
            throw new InvalidOperationException();
        }

        public override void SetValue(object newValue)
        {
            throw new InvalidOperationException();
        }


        #region IDisposable Members

        public void Dispose()
        {
            if (_factory != null)
            {
                _factory.Close();
            }
        }

        #endregion
    }

Coté enregistrement, c’est aussi simple qu’avec un proxy:

 
 container.RegisterType<ICalcChannel>(new WCFLifetimemanager<ICalcChannel>());

Nous pouvons écrire cela maintenant:

 
   var calc = container.Resolve<ICalcChannel>();
   if (calc.State == System.ServiceModel.CommunicationState.Opened)
   {
     ...
   }

Il est toujours possible de passer par la conf pour faire cette opération, mais si l’on veut passer par code, on peut encore un peu se simplifier la vie par une méthode d’extension:

  
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Client_ConfByCode;

namespace Microsoft.Practices.Unity
{
    public static class UnityContainerExtensions
    {
        /// 
        /// Register a service in the given UnityContainer for the specified endpoint
        /// 
        /// 
        /// 
        /// 
        /// 
        public static IUnityContainer RegisterService<T>(this IUnityContainer container, string endpoint) where T : IDisposable
        {
            return container.RegisterType<T>(new WCFLifetimemanager<T>(endpoint));
        }

        /// 
        /// Register a service in the given UnityContainer with the "*" endpoint
        /// 
        /// 
        /// 
        /// 
        /// 
        public static IUnityContainer RegisterService<T>(this IUnityContainer container) where T : IDisposable
        {
            return container.RegisterType<T>(new WCFLifetimemanager());
        }
    }
}

Et l’enregistrement devient encore plus simple:

  
	ret.RegisterService<ICalCchannel>();

Les sources du billet sont ici.

A+

Publié lundi 7 septembre 2009 08:00 par Miiitch
Classé sous : , , , ,
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

Pas de commentaires
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01