WCF: атрибут DataMember для свойства и элемента - PullRequest
53 голосов
/ 17 февраля 2009

В wcf, в чем разница между применением атрибута DataMember к свойству

private int m_SomeValue;

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

вместо переменной-члена

[DataMember]  
private int m_SomeValue;

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

Ответы [ 7 ]

41 голосов
/ 17 февраля 2009

В целом, вы должны предпочесть применение атрибута DataMember к свойству, а не к приватному полю. Единственная причина, по которой вместо этого можно применить атрибут к полю, состоит в том, что свойство было доступно только для чтения (то есть оно не имеет установщика).

24 голосов
/ 17 февраля 2009

Пока вы используете маркер Name, контракт будет одинаковым независимо от того, используется ли поле или свойство.

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

Однако могут быть некоторые проблемы с правами доступа к частным пользователям, в частности для silverlight и CF - в этом случае я бы рекомендовал использовать публичное свойство в качестве члена данных. На самом деле, я бы всегда использовал свойство, если у меня не было очень веской причины ...

6 голосов
/ 28 мая 2010

Есть веские причины, по которым вы можете пометить поля, а не свойства как DataMember.

Пожалуйста, проверьте это для более подробной информации: http://blog.walteralmeida.com/2010/05/wcf-and-datacontract-serialization-internals-and-tips-.html

Кстати: ContractSerializer будет сериализовать любое приватное поле с атрибутом DataMemberAttribute , только если работает в среде полного доверия . Не работает при частичном доверии (проверьте решение в блоге, указанном выше)

4 голосов
/ 09 декабря 2011

Это решение зависит от использования вами службы WCF:

  1. Внутренняя служба, используемая вашими собственными .NET-системами, использующими ту же модель домена.
  2. Внешняя служба, используемая различными платформами, которые не используют одну и ту же модель домена.

Дело 1.

Сериализация - это процесс сохранения состояния объекта. Состояние объекта в C # представлено его полями данных.

Свойства в C # по сути - методы, которые манипулируют состоянием объекта. Их использование может привести к различной десериализации состояния объекта, поскольку порядок, в котором устанавливаются свойства, может влиять на его конечное состояние данных. Другие факторы также могут привести к неправильной десериализации состояния, если, например, метод (набор свойств) зависит от некоторого изменяющегося контекста, например текущего DateTime.

Вы можете сказать, что насчет инкапсуляции? Я не хочу, чтобы мой объект находился в недопустимом состоянии, и я должен выполнять проверки достоверности, проверки целостности графа объектов и т. Д. Да, вы должны, поэтому мы помещаем атрибуты DataMember на подпорки? №

Проблема в том, что многие люди смешивают две разные вещи: DTO (объект передачи данных, контракт WCF) с сущностью домена. Что вам нужно, это убедиться, что данные, которые вы получаете, точно те же данные, которые были отправлены, а затем убедитесь, что вы можете создать действительный объект домена из этих данных. Лучший способ добиться этого - использовать отдельные классы для DTO и создавать из них Domain Entity.

Но большинство программистов ленивы, и им нравится просто украшать Domain Entity с атрибутами DataMemeber. В этом случае решение Field или Prop зависит от того, где находится ваша логика валидации, если ваша логика валидации похоронена в методах Set, вам придется использовать Props, если он является внешним, вы должны использовать Fields, и валидировать вашу Domain Entity после десериализации.

P.S. Я думаю, что те же правила применимы к любому процессу сериализации, как постоянство базы данных.

Также я хотел бы отметить, что Silverlight не может сериализовать \ десериализовать приватные поля, потому что вы не можете получить к ним доступ извне, используя отражение, и вам придется сделать их приватными и использовать InternalsVisibleToAttribute.

Дело 2.

Это сложный вопрос. Основное внимание здесь уделяется взаимодействию. В 99,9% у вас будут отдельные классы DTO в этом случае и, скорее всего, множество различных версий для поддержки старых клиентов. Неважно, куда вы помещаете атрибуты DataMembers, потому что вы используете DTO. Я не буду объяснять этот сценарий, потому что разработчики, работающие в такой крупномасштабной системе, как правило, достаточно опытны и не читают SO.

3 голосов
/ 17 февраля 2009

Теоретически, и пока вы держите m_SomeValue всегда равным SomeValue (как простой метод получения / установки), ничего. Кроме имени переменной, предоставляемой WCF. (Очевидно, что если вы пометите переменную m_, ваш прокси-класс также будет иметь то же имя m_. Прокси-класс сгенерирует открытое свойство независимо от того, используете ли вы открытое / защищенное / внутреннее / личное поле или свойство.

Однако, если в ваших методах доступа есть какая-то специальная логика, которая может изменять возвращаемое значение (например, ToUpper() с использованием строки), вы должны вернуть другое значение.

2 голосов
/ 27 октября 2009

Лично я бы просто использовал это свойство и полностью удалил переменную-член все вместе. т.е.

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

Свойство необъяснимым образом создаст переменную-член за сценой.

1 голос
/ 21 мая 2010

Если добавить [DataMember] в закрытое int m_SomeValue, этот элемент не может быть сериализацией, поэтому необходимо добавить его в public int SomeValue.

[DataMember]  
private int m_SomeValue;

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

приведенный выше код не может получить значение в клиенте, если вы используете его через WCF.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...