2010-10-06 24 views
1

Nous appliquons tous nos objets de domaine pour implémenter GetHashCode. Lorsque nous exposons ces objets de domaine via WCF, le service généré suivant nécessite une modification post-mise à jour pour compiler.Méthodes pour conserver le côté serveur de la méthode abstraite pour WCF

//------------------------------------------------------------------------------ 
// <auto-generated> 
//  This code was generated by a tool. 
//  Runtime Version:2.0.50727.3053 
// 
//  Changes to this file may cause incorrect behavior and will be lost if 
//  the code is regenerated. 
// </auto-generated> 
//------------------------------------------------------------------------------ 

namespace IdCardManagerServiceReference { 
using System.Runtime.Serialization; 
using System; 


[System.Diagnostics.DebuggerStepThroughAttribute()] 
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")] 
[System.Runtime.Serialization.DataContractAttribute(Name="IdCard", Namespace="http://schemas.datacontract.org/2004/07/Entity.Domain")] 
[System.SerializableAttribute()] 
public partial class IdCard : Core.DomainObject, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged { 
    [System.NonSerializedAttribute()] 
    private System.Runtime.Serialization.ExtensionDataObject extensionDataField; 

    [System.Runtime.Serialization.OptionalFieldAttribute()] 
    private int EffDteField; 

    [global::System.ComponentModel.BrowsableAttribute(false)] 
    public System.Runtime.Serialization.ExtensionDataObject ExtensionData { 
     get { 
      return this.extensionDataField; 
     } 
     set { 
      this.extensionDataField = value; 
     } 
    } 

    [System.Runtime.Serialization.DataMemberAttribute()] 
    public int EffDte { 
     get { 
      return this.EffDteField; 
     } 
     set { 
      if ((this.EffDteField.Equals(value) != true)) { 
       this.EffDteField = value; 
       this.RaisePropertyChanged("EffDte"); 
      } 
     } 
    } 
} 

Toutes les idées sur la façon de maintenir l'exigence de GetHashCode, mais supprimer l'exigence de tout code sur le client (comme une mise à jour ou classes partielles)?

+0

Quelle est la modification nécessaire? –

+0

"le service généré suivant nécessite une modification post-mise à jour pour la compilation." Que voulez-vous dire? Quelles modifications avez-vous à faire? –

+0

@Ray @Kirk doit ajouter public override int GetHashCode() {...} à la classe partielle IdCard générée –

Répondre

3

Si vous avez vraiment besoin que tous les C# consommateurs de votre service WCF utilisent les mêmes modèles avec le code d'origine dans le tact puis utilisez la fonction « Ajouter un service de référence » « types de réutilisation dans des assemblages référencés » de l'outil. Veillez à répartir vos modèles/contrats/interfaces en un seul assemblage sans autre code d'implémentation qui serve d'assemblage de "définition" partagé. Marquez cet assembly comme celui à réutiliser lorsque l'outil "Ajouter une référence de service" génère votre code de proxy client. En outre, juste un avertissement proactif: simplifier les choses pour vous-même en ayant une seule implémentation de client de service C# "officielle" pour votre service. N'ajoutez pas de proxys de référence de service redondants générés par Visual Studio à chaque projet nécessitant une connectivité avec votre service.

EDIT:

Parlant de son expérience personnelle récente, ayant conçu une API modulaire, a permis au service, permettez-moi de fournir des conseils plus généraux sur le thème de la modularité en ce qui concerne non seulement pour les services WCF, mais le design global.

Dans notre système, nous avons fait ce que j'ai suggéré ci-dessus en créant un seul ensemble "Définition" qui contient uniquement des objets marqués [DataContract]: objets de domaine, modèles, contrats de données, comme vous voulez.

Dans cet assemblage est également une collection d'interfaces de référentiel qui définit des méthodes uniquement en termes de ces objets de domaine. Il existe également des structures d'identifiants fortement typées définies dans cet assemblage qui sont utilisées pour conserver des valeurs d'identité pour chaque modèle puisque ces modèles sont des bases de données persistantes et ont chacune une colonne d'identité. En utilisant struct qui enveloppent int s de cette manière est préférable d'utiliser int lui-même puisque maintenant nous obtenons l'analyse sémantique assistée par le compilateur, ce Model1ID n'est pas convertible en Model2ID car ils représentent sémantiquement deux domaines différents en dépit du fait que les deux domaines sont représentables par le int type.

Ce qui motive la modularité est la définition de ces interfaces de référentiel. La classe d'implémentation du service WCF implémente simplement toutes les interfaces requises, de même que la classe d'implémentation du client de service WCF, la classe d'implémentation du proxy de mise en cache, la classe d'implémentation de journalisation d'invocation de méthode, etc. autres assemblages, c'est-à-dire pas dans l'ensemble "Définition" qui contient les interfaces et les modèles. Ces classes implémentent les interfaces et apparaissent comme identiques dans le code consommateur.

La clé est de garder votre code de consommateur API indépendant des classes d'implémentation spécifiques et de ne faire référence qu'aux interfaces. Les modèles eux-mêmes sont conservés comme de simples conteneurs de données sans implémentation de logique métier. Je crois que ce modèle est considéré comme anémique, mais pour moi "anémique" a des connotations négatives, donc je n'aime pas utiliser ce terme pour décrire cette conception. Ce que vous obtenez est une logique métier implémentant du code client qui ne se soucie pas de savoir si elle parle à un service WCF ou directement à une base de données, ou si la mise en cache est implémentée de façon transparente ou si les invocations de méthodes sont enregistrées. quels que soient les autres utilisations de proxy que vous pouvez proposer.

En résumé, concevoir avec des interfaces et vous rendre la vie plus facile. Mais faites-le seulement si vous êtes confiant dans votre capacité à pratiquer la retenue. Dans notre système que j'ai conçu, nous avons des modèles T4 qui génèrent presque tout le code standard qui accompagne les services WCF au point où tout ce que nous avons à faire manuellement est de définir le modèle, de concevoir l'interface et d'écrire le code d'accès . La façade WCF est gratuite avec un simple clic-droit et "Run Custom Tool" sur les modèles T4. J'aime ça. :)

+1

Eactly. TRES bonne approche, et cela permet de mettre une logique simple dans les objets (comme la validation frontale). – TomTom

+0

La modularité est toujours une bonne approche! J'ai plus de conseils à donner sur ce sujet mais je dois me contraindre à la question à portée de main pour le bien de SO :) –

+0

Si c'est en référence à la modularité WCF je crois qu'il se rapporte. –

0

Corrigez l'espace de noms sur votre classe partielle. Vous devrez peut-être ajuster les attributs et l'héritage.

namespace DCS2000.IDCardExclude.UI.IdCardManagerServiceReference 
{ 
    [Serializable] 
    [DataContract] 
    public partial class IdCard : DomainObject 
    { 
    public override int GetHashCode() 
    { 
     return EffDte.GetHashCode(); 
    } 
    } 
} 
+0

Indépendamment de l'espace de noms, si vous savez ce qu'il sera dans la classe générée, vous pouvez créer la classe partielle pour implémenter GetHasCode() et elle ne sera pas redéfinie lorsque vous créez votre référence. –

+0

c'est une bonne solution pour une résolution côté client et peut-être le meilleur. Des idées sur quelque chose qui ne nécessitera pas de fichiers de classe partielle? –