2009-02-09 4 views
20

J'ai une bibliothèque de classe C# et un projet de démarrage (une application de console). La bibliothèque de classes inclut une référence de service à un service Web. Lorsque j'essaie d'exécuter le projet, j'obtiens une exception InvalidOperationException car le projet de démarrage ne lit pas le fichier app.config de la bibliothèque de classes et ignore la référence du service. Pour que cela fonctionne, je suis obligé d'ajouter la même référence de service au projet de démarrage. Est-ce que je peux éviter cela? Puis-je faire en sorte que le projet de démarrage reconnaisse la référence de service de la bibliothèque de classes et app.config sans avoir à le copier dans le projet de démarrage?Ajout d'une référence de service à partir d'une bibliothèque de classes

J'ai essayé d'ajouter un lien vers le fichier app.config de la bibliothèque de classes, mais cela ne fonctionne pas. La bibliothèque de classes n'est pas très portable si elle nécessite que quiconque l'utilise ajoute cette référence de service au projet de démarrage.

+0

+1 : Hey Zarjay, j'allais poser la même question. Bien que je sois d'accord avec Andrew Hare, et que je comprenne pourquoi cela n'est pas possible, je suis également d'accord sur le fait que la solution ne rend pas vraiment la bibliothèque très portable. Je me demande si les paramètres de configuration peuvent être appliqués par programmation. – andy

+0

Je ne suis pas sûr, mais j'en doute. Idée géniale, cependant. Je sais qu'il est possible d'écrire dans le fichier de configuration, mais je parie que lorsque votre code le permet, il est probablement trop tard pour ajouter une référence de service. –

Répondre

14

Pensez à ce que vous essayez de faire - vous avez deux ensembles que vous construisez:

Library 
ConsoleApp 

Ces deux ensembles ont des fichiers de configuration - j'imagine qu'ils ressemblent à ceci:

Library 
    app.config 
ConsoleApp 
    ConsoleApp.exe.config 

Lorsque vous exécutez ConsoleApp, il n'a aucun moyen de lire ou de connaître app.config à partir de votre assemblage Library. Le seul fichier de configuration dont il sait ou se soucie est ConsoleApp.exe.config. Maintenant, il est possible que les fichiers de configuration se réfèrent les uns aux autres, mais ce n'est pas la bonne solution pour ce que vous essayez de faire.

Étant donné que votre assembly Library n'a aucun point d'entrée, il ne sera jamais chargé dans un AppDomain. Comme il ne sera jamais chargé dans un AppDomain, son fichier de configuration d'application ne sera jamais utilisé.

Ce que vous devez faire est de référence Library dans ConsoleApp via une référence de projet. Ensuite, déplacez toutes les données de configuration pertinentes de app.config vers ConsoleApp.exe.config car il s'agit du fichier de configuration qui sera utilisé par votre application.

Cela vous permettra d'avoir deux choses que vous devez appeler des méthodes sur votre service Web

  1. Le code Library qui peut envoyer et recevoir des messages SOAP. Les métadonnées de configuration requises par Library pour fonctionner.
+0

Merci pour l'explication; est logique maintenant pourquoi cela ne fonctionnait pas. Je suis encore nouveau sur .NET, et même si je préfère que la bibliothèque de classes soit un module autonome dont l'implémentation interne n'est pas pertinente pour le code qui l'utilise, je comprends maintenant pourquoi cela ne fonctionne pas dans cette situation. –

+0

Pour ce que cela vaut, les données de configuration ne sont pas une implémentation interne: ce sont les données de configuration de bibliothèque qui doivent être fournies par l'utilisateur de la bibliothèque (votre application de console). Ma pratique générale consiste à fournir l'exemple de configuration dans un fichier app.config avec le projet de bibliothèque lorsqu'un fichier de configuration est demandé, puis à supposer que l'utilisateur de la bibliothèque copie les données de configuration dans son propre fichier de configuration, en modifiant approprié. Si le fichier de configuration n'est pas requis, ces options deviennent simplement des boutons de configuration programmatiques dans la bibliothèque. –

+7

Greg, je ne suis pas d'accord. Les données de configuration de bibliothèque correspondraient à une URL de service Web que le développeur connaîtrait, pas à l'utilisateur. L'utilisateur ne devrait pas avoir à se soucier de ce que cette URL est; c'est une implémentation interne d'une bibliothèque, et en tant qu'utilisateur de l'interface (la bibliothèque), je ne devrais pas m'inquiéter des détails de l'implémentation (le service web qu'elle utilise). Dieu merci, je peux utiliser les bibliothèques client Java de Google sans se soucier des URL qu'il utilise pour exécuter ses fonctions. Malheureusement, s'il y avait une version .NET, je serais obligé de m'en soucier. Ne pas avoir cette option est une grosse faille dans .NET à mon avis. –

0

Vous avez juste besoin de copier la clé de configuration, en pointant sur le service, à partir du fichier de configuration de votre bibliothèque de classes vers le fichier de configuration de votre application de console.

+0

Mon app.config n'a pas de clé de configuration. Comment en spécifier un? –

+0

Lorsque vous référencez un service Web, vous pouvez choisir d'utiliser une référence statique ou dynamique, voir Propriétés. Si vous choisissez dynamic, l'EDI génère du code, dans votre classe de proxy de service Web, pour lire l'URL du fichier de configuration. Copiez les valeurs générées dans la configuration de la bibliothèque vers la configuration de votre application de console. –

0

Je pense que c'est plus déroutant si vous aviez plusieurs fichiers de configuration en cours d'exécution.

Si une bibliothèque a des éléments configurables, je m'attendrais à devoir mettre cette configuration dans mon fichier de configuration pour consommer correctement la bibliothèque.

1

Vous pouvez copier les parties pertinentes du fichier app.config de la configuration de la bibliothèque de classes dans le fichier app.config de l'application console. Alternativement, si vous essayez vraiment de le rendre vraiment portable, vous devrez penser à une autre manière de référencer l'adresse pour la référence de service spécifique à partir de la bibliothèque de classes.

+0

J'ai essayé de copier sur app.config, mais l'application console ne sera pas exécutée à moins que j'ajoute la référence de service. La portabilité n'est vraiment pas une priorité; Je trouve juste ennuyeux d'inclure de manière redondante quelque chose dans un projet. La bibliothèque de classes devrait être autonome. –

+0

Les bibliothèques de classes qui sont des clients WCF ne sont pas volontairement autonomes. Ils ne sont généralement pas destinés à la redistribution. Ils sont destinés à être configurables du côté client, ce qui explique pourquoi le fichier app.config est typique de ceux-ci. Vous pouvez toujours coder en dur la valeur, mais c'est ... bien ... coder en dur. :) –

3

Une alternative à l'utilisation d'une référence de service dans la bibliothèque de classes et de la copie de la config serait d'utiliser des événements de génération qui appellent svcutil.exe. Ce que j'aime à ce sujet, c'est que vous n'avez pas à faire de "mise à jour du service de référence" lorsque le service change. Il sera mis à jour automatiquement.

Dans la bibliothèque de classes, utilisez un événement de construction qui ne génère que le code proxy:

svcutil.exe net.tcp://localhost:3315/MyService/mex /noConfig 

Dans l'application, utilisez un événement de construction qui génère la configuration. Vous pouvez utiliser l'option/mergeConfig pour la fusionner dans un app.config existant.

svcutil.exe net.tcp://localhost:3315/MyService/mex 
      /config:App.config /mergeConfig 

Si vous ne voulez pas obtenir une erreur de construction si le service ne fonctionne pas, mettez dans votre fichier de projet et vous obtiendrez un message d'avertissement au lieu d'une erreur:

<Target 
    Name="PreBuildEvent" 
    Condition="'$(PreBuildEvent)'!=''" 
    DependsOnTargets="$(PreBuildEventDependsOn)"> 
    <Exec WorkingDirectory="$(OutDir)" 
     Command="$(PreBuildEvent)" 
     ContinueOnError="true" /> 
</Target> 
Questions connexes