Question

J'ai un service WCF hébergé dans IIS. Le but est que les clients passent un appel et reçoivent une classe personnalisée définie dans un autre projet / dll. J'ai généré un client de service à l'aide de svcutil.exe. Le problème est que ce client généré automatiquement contient une nouvelle définition partielle / proxy pour la classe que je tente de renvoyer depuis le service. Il génère maintenant une erreur de conversion entre ma classe personnalisée d'origine et la nouvelle définition partielle au moment de la compilation. Alors, comment renvoyez-vous les types définis par l'utilisateur à partir d'un service WCF? Conseils appréciés.

Était-ce utile?

La solution

Juste pour la seconde Yossi / Les pensées de Rich :

  • oui, vous pouvez ajouter une référence à la dll partagée (plutôt que d'utiliser la classe proxy générée)
  • Oui, cela va à l'encontre de l'intention des contrats de données. Si un type quelconque de sérialisation est en cours, vous pourriez avoir des problèmes pour étendre votre service

Je suis déjà allé dans cette voie et, à certains égards, je n’aurais pas aimé. Extensibilité / sérialisation personnalisée - vous devez être très prudent. Un peu plus facile si vous utilisez un sérialiseur prérempli tel que protobuf-net ( qui peut s’intégrer directement dans WCF et qui est conçu pour être extensible), mais pas facile.

En fait, un avantage du partage des classes est que le test est un peu plus simple: puisque vous avez le même IFoo partout, vous pouvez vous moquer de ce IFoo avec une chance raisonnable de succès. Il est plus difficile de se moquer lorsque le proxy est impliqué (car vous modifiez davantage de pièces mobiles entre le code de test et le code de production).

Autres conseils

Si le type que vous souhaitez renvoyer à partir de votre appel de service n'est pas marqué comme DataContract , vous ne pourrez pas le renvoyer à partir de WCF sans fournir une copie de ce même assembly à votre client. application.

using System;
using System.ServiceModel;

[ServiceContract]
interface IService
{
    [OperationContract]
    TimeSpan GetTimeSpan();
}

class Service : IService
{
    public TimeSpan GetTimeSpan() { return DateTime.Now.TimeOfDay; }
}

Pourquoi le code précédent fonctionne-t-il alors? Cela fonctionne parce que les deux côtés de l'appel de service ont System.dll afin qu'ils connaissent le type System.TimeSpan , qui est le type de retour du type OperationContract GetTimeSpan ( ) .

Voici un exemple utilisant un DataContract :

using System;
using System.ServiceModel;
using System.Runtime.Serialization;

[ServiceContract]
interface IService
{
    [OperationContract]
    Contract GetContract();
}

[DataContract]
class Contract
{
    [DataMember]
    public String MyProperty { get; set; }
}

class Service : IService
{
    public Contract GetContract() { return new Contract(); }
}

Vous avez maintenant fourni les attributs de sérialisation à une classe que vous avez définie ( Contrat ) - cela vous permettra d'utiliser svcutil.exe pour créer des classes proxy dans votre application client. qui sera sérialisé et envoyé au service WCF.

Désormais, si vous souhaitez renvoyer un type autre que DataContract , vous devez fournir une copie de l'assembly contenant ce type à votre application client.

L’une des choses à faire est que l’utilisateur doive configurer la référence de service pour utiliser vos types à partir de la DLL plutôt que la classe définie par le proxy - http://msdn.microsoft.com/en-us/library/bb628653.aspx

Nous avons emprunté cette voie dans le passé, et le problème est qu’il s’agit bien entendu de deux classes différentes. Vous devrez donc suivre le lien fourni par @Rich Reuter;

Nous avons cependant appris à nos dépens que c’est une mauvaise pratique, car elle va à l’encontre du 3ème principe du schéma de partage de services et du contrat de services, et non de la classe.

Bien entendu, le problème ne consiste pas simplement à ne pas suivre une "règle". établi par quelqu'un à un moment donné, mais qu'il y avait de bonnes raisons de suggérer ceci - nous avons appris que le prix d'un tel couplage étroit entre le service et le client signifie qu'il est très difficile de le libérer non plus - si le service doit ajouter un autre champ de cette classe, pour servir un autre client - le premier client pourrait être affecté; si le service doit changer quelque chose dans cette définition de classe (pour servir un autre client) - le premier client sera à nouveau affecté, et inversement - le client peut affecter le cycle de vie du service.

Dans les grands projets, cela devient rapidement une lourde charge de maintenance.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top