53 votes

WCF : Attribut DataMember sur la propriété vs. le membre

Dans le cadre de wcf, quelle est la différence entre l'application du DataMember sur une propriété

private int m_SomeValue;

[DataMember]  
public int SomeValue {
  get {...}
  set {...}
}

au lieu d'une variable membre

[DataMember]  
private int m_SomeValue;

public int SomeValue {
  get {...}
  set {...}
}

?

41voto

dthrasher Points 10641

En général, il est préférable d'appliquer l'attribut DataMember sur la propriété plutôt que sur le champ privé. La seule raison d'appliquer l'attribut au champ est que la propriété est en lecture seule (c'est-à-dire qu'elle n'a pas de setter).

24voto

Marc Gravell Points 482669

Tant que vous utilisez le Name marqueur, le contrat est identique, que le champ ou la propriété soit utilisé.

[DataMember(Name="SomeValue")]
private int m_SomeValue;

Cependant, il peut y avoir des problèmes de permissions pour accéder aux membres privés, en particulier sur silverlight et CF - dans ce cas, je recommanderais d'utiliser la propriété publique comme membre de données. En fait, j'aurais tendance à toujours utiliser une propriété à moins d'avoir une très bonne raison...

6voto

Walter Almeida Points 157

Il y a de bonnes raisons pour lesquelles vous pouvez vouloir marquer les champs plutôt que les propriétés comme DataMember .

Veuillez consulter cette page pour plus de détails : http://blog.walteralmeida.com/2010/05/wcf-and-datacontract-serialization-internals-and-tips-.html

Au fait : Les sérialiseurs de contrats sérialisent tout champ privé qui possède l'attribut DataMemberAttribute. uniquement si vous travaillez dans un environnement de confiance totale . Ne fonctionne pas dans le cadre d'une confiance partielle (consultez le blog mentionné ci-dessus pour trouver une solution).

4voto

Alex Burtsev Points 4251

Cette décision dépend de l'utilisation de votre service WCF :

  1. Service interne consommé par vos propres systèmes .NET, qui partagent le même modèle de domaine.
  2. Service externe consommé par différentes plateformes, qui ne partagent pas le même modèle de domaine.

Cas 1.

La sérialisation - est le processus de persistance de l'état de l'objet. L'état de l'objet en C# est représenté par ses champs de données.

Les propriétés en C# sont essentiellement des méthodes qui manipulent l'état de l'objet. Leur utilisation peut entraîner un état différent de l'objet après la désérialisation, car l'ordre dans lequel les propriétés sont définies peut avoir un impact sur l'état final des données. D'autres facteurs peuvent également entraîner une désérialisation incorrecte de l'état de l'objet, si par exemple la méthode (ensemble de propriétés) repose sur un contexte qui change, comme l'heure actuelle.

Vous pourriez dire : "Et l'encapsulation ? Je ne veux pas que mon objet soit dans un état invalide, et je dois faire des contrôles de validation, des contrôles d'intégrité du graphe de l'objet, etc. Oui, vous devriez, donc nous mettons les attributs DataMember sur les props ? Non.

Le problème ici est que beaucoup de gens mélangent deux choses différentes, DTO (Data Transfer Object, WCF Contract) avec Domain Entity. Ce dont vous avez besoin, c'est de vous assurer que les données que vous recevez sont exactement les mêmes que celles qui ont été envoyées, et ensuite de vous assurer que vous pouvez construire une entité de domaine valide à partir de ces données. La meilleure façon d'y parvenir est d'utiliser des classes séparées pour les DTO, et de construire des entités de domaine à partir de celles-ci.

Mais la plupart des programmeurs sont paresseux, et ils aiment simplement décorer l'entité de domaine avec des attributs DataMemeber. Dans ce cas la décision Field ou Prop dépend de l'endroit où se trouve votre logique de validation, si votre logique de validation est enterrée dans les méthodes Set, vous devrez utiliser les Props, si c'est extensif vous devriez utiliser les Fields, et valider votre entité de domaine après désirialization.

P.S. Je pense que les mêmes règles s'appliquent à tout processus de sérialisation, comme la persistance de la base de données.

Aussi, je voudrais mentionner que Silverlight ne peut pas sérialiser \deserialize les champs privés, car vous ne pouvez pas y accéder de l'extérieur en utilisant la réflexion, et vous devrez les rendre privés et utiliser InternalsVisibleToAttribute.

Cas 2.

C'est difficile. L'objectif principal ici est l'interopérabilité. Dans 99,9% des cas, vous aurez des classes de DTO séparées dans ce cas et très probablement beaucoup de versions différentes de celles-ci pour supporter les anciens clients. L'endroit où vous placez les attributs DataMembers n'a pas d'importance, car vous utilisez des DTO. Je ne prendrai pas la peine d'expliquer ce scénario, car les développeurs qui travaillent sur de tels systèmes à grande échelle sont généralement assez expérimentés, et ils ne prennent pas la peine de lire le SO.

3voto

Jarrett Meyer Points 11147

En théorie, et tant que vous gardez m_SomeValue toujours égal à SomeValue (comme un simple getter/setter), rien. Autre que le nom de la variable exposée par la WCF. (Évidemment, si vous marquez le m_ votre classe proxy aura également la même variable m_ nom. La classe proxy générera une propriété publique, que vous utilisiez un champ ou une propriété publique/protégée/interne/privée.

Cependant, si vous avez une logique spéciale dans vos accesseurs qui peut modifier la valeur retournée ( ToUpper() une chaîne de caractères, par exemple), vous renverrez une valeur différente.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X