Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Thomas Lebrun

Tout sur WPF, LINQ, C# et .NET en général !

Actualités

[MEF] Comment utiliser un fichier de configuration dans vos plugins ?

Voici un problème qui, priori, n’en est pas un Smile

En effet, j’ai récémment eu besoin, dans un plugin utilisé par une application Silverlight utilisant MEF, d’appeler un service WCF. Jusque là, rien de bien sorcier me direz-vous: j’ajoute la référence à mon service et, dans mon plugin, je fais un simple:

   1: TheService.Service1Client client = new Service1Client();

Je teste l’application et là, c’est le drame !

image

Après investigations, il s’avère que c’est parce que l’application principale (qui hoste les plugins) n’as pas de fichier de configuration comportant les informations indiquées dans le fichier de configuration du plugin…

Après quelques recherches sur Internet, je trouve la solution de quelqu’un qui a le même problème en utilisant Prism. Sa solution, simple dans les faits, consiste à ajouter le fichier de configuration du plugin comme lien à l’application principale. Cette solution ne me convenait pas car:

  • Mon application principale avait déjà un fichier de configuration
  • Je veux que mes plugins soient complètement indépendants les uns des autres et de l’application qui les charges: si celle-ci doit connaitre le contenu des fichiers de configurations des plugins, comment ferais-je le jour où je disposerais d’un plugin tiers ?

Bref, il a donc fallut trouver un idée qui, au final, est simple comme bonjour: puisque les informations (adresse, type de binding, etc.) sont toutes présentes dans le fichier de configuration, pourquoi ne pas y accéder et créer le proxy en lui spécifiant ces informations ?

J’ai donc commencer par mettre le fichier de configuration de mon plugin en Resource puis, à l’aide de la méthode suivante, j’accède à l’adresse du service:

   1: /// <summary>
   2: /// Reads the address from the file ServiceReferences.ClientConfig.
   3: /// </summary>
   4: /// <param name="contract">The contract.</param>
   5: private static EndpointAddress ReadAddress(string contract)
   6: {
   7:     EndpointAddress result = null;
   8:  
   9:     var streamInfo = Application.GetResourceStream(new Uri("/" + GetNameFromFullName(Assembly.GetExecutingAssembly().FullName) + ";component/ServiceReferences.ClientConfig", UriKind.Relative));
  10:     if (streamInfo != null)
  11:     {
  12:         var config = XDocument.Load(streamInfo.Stream);
  13:         var endpoints = from endpoint in config.Descendants("endpoint")
  14:                         where endpoint.Attribute("contract").Value == contract
  15:                         select new {Address = endpoint.Attribute("address").Value};
  16:  
  17:  
  18:         foreach (var endpoint in endpoints)
  19:         {
  20:             result = new EndpointAddress(endpoint.Address);
  21:         }
  22:  
  23:         if (result == null)
  24:         {
  25:             throw new InvalidOperationException(string.Format("Cannot create endpoint for contract {0}.", contract));
  26:         }
  27:  
  28:         return result;
  29:     }
  30:  
  31:     throw new InvalidCastException("streamInfo must not be null !");
  32: }
  33:  
  34: /// <summary>
  35: /// Gets the name from the full name.
  36: /// </summary>
  37: /// <param name="fullName">The full name.</param>
  38: private static string GetNameFromFullName(string fullName)
  39: {
  40:     return fullName.Substring(0, fullName.IndexOf(','));
  41: }

Ensuite, il ne reste plus qu’à utiliser cette méthode pour récupérer l’adresse du service et instancier le proxy en lui passant les paramètres:

   1: EndpointAddress address = ReadAddress("TheService.Service1");
   2: if (address != null)
   3: {
   4:     TheService.Service1Client client = new Service1Client(new BasicHttpBinding(), address);
   5:     client.SayHelloCompleted += this.client_SayHelloCompleted;
   6:     client.SayHelloAsync("Thomas");
   7: }

Et le tour est joué Smile

Bien sûr, il faut sans doute améliorer cette technique pour qu’elle permette de lire toutes les informations sur le Endpoint (adresse, binding, paramètres de binding, etc.) mais c’est un bon début Wink

 

A+

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 :
Posted: mardi 3 novembre 2009 10:09 par Thomas LEBRUN
Classé sous : , , ,

Commentaires

vruiz a dit :

La classe ServiceModelSectionGroup permet de lire les config WCF, en tout cas quand on a physiquement le fichier. Pas sûr qu'on puisse utiliser cette méthode pour lire un fichier en ressource.

ExeConfigurationFileMap executionFileMap = new ExeConfigurationFileMap();

           executionFileMap.ExeConfigFilename = "App.config";

           Configuration config = ConfigurationManager.OpenMappedExeConfiguration(executionFileMap, ConfigurationUserLevel.None);

           ServiceModelSectionGroup serviceModeGroup = ServiceModelSectionGroup.GetSectionGroup(config);

# novembre 3, 2009 13:59

cyril a dit :

J'ai eu la meme problèmatique : comment lire la configuration WCF sans la mettre dans le fichier de configuration de l'application "hôte". J'ai utilisé la même solution : lire le fichier de config manuellement :(

Cependant, j'avais utilisé l'objet Configuration ainsi que les sections, j'ai également lu le fichier depuis le disque plutot que dans les ressources, cela me permettait de faire des modifications de config sans recompiler.

D'ailleurs, je serais curieux de voir comment ASP.net gère les fichiers de config qui se trouvent dans des sous-dossiers.

Cyril DURAND

# novembre 3, 2009 16:30

sebeuh a dit :

J'ai eu aussi cette problèmatie lors du developpement de notre projet ImagineCup HelpAged en developpant un Addin VisualStudio permettant d'envoyer les applications sur le HAAS (HelpAged Application Store) directement depuis VS (en passant par un WS hebergé sur Azure) !

Le problème c'est notre Addin VS ne peut acceder à la configuration via le ConfigurationManager ce qui est problèmatie lors de l'utilisation de WCF.

Pour cela nous avons créer un Custom Chanel comme évoqué sur ce post : http://weblogs.asp.net/cibrax/archive/2007/10/19/loading-the-wcf-configuration-from-different-files-on-the-client-side.aspx

# novembre 3, 2009 18:22
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Emportez votre sélection de la MSDN dans la poche ? par Blog de Jérémy Jeanson le il y a 21 heures et 42 minutes

- [ #Office365 ] Pb de connexion du flux Yammer ajouté à un site SharePoint par Le blog de Patrick [MVP SharePoint] le 04-17-2014, 17:03

- NFluent & Data Annotations : coder ses propres assertions par Fathi Bellahcene le 04-17-2014, 16:54

- Installer un site ASP.net 32bits sur un serveur exécutant SharePoint 2013 par Blog de Jérémy Jeanson le 04-17-2014, 06:34

- [ SharePoint Summit 2014 ] Tests de montée en charge SharePoint par Le blog de Patrick [MVP SharePoint] le 04-16-2014, 20:44

- [ SharePoint Summit 2014 ] Bâtir un site web public avec Office 365 par Le blog de Patrick [MVP SharePoint] le 04-16-2014, 18:30

- Kinect + Speech Recognition + Eedomus = Dommy par Aurélien GALTIER le 04-16-2014, 17:17

- [ SharePoint Summit 2014 ] Une méthodologie simple pour concevoir vos applications OOTB SharePoint de A à Z par Le blog de Patrick [MVP SharePoint] le 04-16-2014, 16:51

- //Lean/ - Apprendre à faire des Apps Windows universelles par Blog de Jérémy Jeanson le 04-16-2014, 12:57

- Une culture de la donnée pour tous… par Le blog de Patrick [MVP SharePoint] le 04-16-2014, 11:00