2011-06-11 2 views
8

Мне нужно, чтобы некоторые члены данных получили некоторые значения, когда я создаю экземпляр DataContract на клиенте. Этого не происходит с помощью конструкторов. Я просматривал различные форумы и обнаружил, что мы должны использовать атрибуты [OnDeserializing] и [OnDeserialized]. Это также не работает. Может кто-нибудь что-то предложить здесь. Другой альтернативой является создание конструкторов в частичных классах на стороне клиента. Я хочу этого избежать.Конструктор в WCF DataContract не отражается на клиенте

Вы можете найти код ниже:

стороны сервера: DataContract

[DataContract] 
public class Account 
{ 

    private int mAccountId; 
    private string mAccountName; 

    public Account() 
    { 
     mAccountId = 5; 
     mAccountName = "ABC"; 
    } 

    [OnDeserializing] 
    public void OnDeserializing(StreamingContext context) 
    { 
     mAccountId = 5; 
     mAccountName = "ABC"; 
    } 

    [OnDeserialized] 
    public void OnDeserialized(StreamingContext context) 
    { 

    } 

    [DataMember] 
    public int AccountId 
    { 
     get 
     { 
      return mAccountId; 
     } 
     set 
     { 
      mAccountId = value; 
     } 
    } 

    [DataMember] 
    public string AccountName 
    { 
     get 
     { 
      return mAccountName; 
     } 
     set 
     { 
      mAccountName = value; 
     } 
    } 


} 

стороны клиента - инициализация

namespace TestClient 
{ 
    public partial class _Default : System.Web.UI.Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      Account acc = new Account(); 

     } 
    } 
} 
+0

Соединение клиент-сервер WCF будет ** ** ** зеркально отражать аспекты данных ваших контрактов данных - ** не ** любой код, который может быть у вас в классах данных. В конце концов: только данные могут быть сериализованы в формат, представленный XSD (XML-схемой) и отправленный по проводу - без кода. –

ответ

14

кода генератор используется для создания WCF прокси-классов создает совместимые типы контрактов , и не использует тот же самый тип, который используется службой WCF. Самый простой способ добиться того, что вы хотите, чтобы создать конструктор самостоятельно на клиентском компьютере, так как код генерируемый partial:

partial class Account 
{ 
    public Account() 
    { 
     AcountId = 5; 
     AccountName = "ABC"; 
    } 
} 

Если вы не хотите, чтобы это сделать, вы можете получить WCF для повторного использования типов которые уже ссылаются на ваш проект клиента. Поэтому, если ваши классы контрактов данных находятся в отдельной библиотеке (как рекомендуется), вы можете ссылаться на эту библиотеку, а затем перенастроить свой проект клиента WCF, чтобы повторно использовать общие типы из ссылочной сборки.

+0

любое другое обходное решение? Почему атрибуты [OnDeserializing]/[OnDeserialized] не работают ..... Спасибо ... – Subhasis

+0

Поскольку эти атрибуты предназначены для десериализации = когда вы получаете «Учетную запись» из службы, а не при вызове конструктора! –

+2

+1 для размещения классов datacontract в другой библиотеке. Мы поместили их в библиотеку с определением интерфейса службы, и на самом деле договоры на связь являются проблемой обслуживания, а не проблемой модели домена. –

13

Свойства, связанные с атрибутами DataMember, определяют только то, что будет включено в генерируемый WSDL/XSD. Клиент будет генерировать свои собственные классы, основанные на wsdl/xsd, которые будут использоваться для связи с сервисом. Он не использует те же классы, которые используются на сервере.

Вот почему вы не получите:

  • любых конструкторов, определенных в DataContract классе
  • любого частные [DataMember] свойств/полей (клиент всегда будет создавать общественные свойства/поля)
  • любого поведения определенные в классе DataContract

Представьте сценарий, когда клиент java хочет подключиться к вашему сервису. Вы ожидаете, что классы Java будут сгенерированы с помощью одного и того же конструктора? Как насчет атрибутов [OnDeserialized]? Как насчет клиента java-скрипта или клиента python?

Когда вы начинаете думать об этом таким образом, вы начинаете понимать, почему у вас не может быть того, что вы хотите (по крайней мере, не обмениваясь библиотеками между клиентом и сервером).

Реальность заключается в том, что вы не можете заставить клиента иметь классы, которые всегда имеют значения по умолчанию, и вы не можете для клиента всегда отправлять обратно действительные данные, клиент всегда может просто отправить сообщение, содержащее мусор, если он захочет. У вас есть небольшой контроль над некоторыми аспектами сообщения с помощью IsRequired и «EmitDefaultValue», которые будут добавлять проверки в xsd, чтобы убедиться, что что-то присутствует в сообщении, но вам нужно будет выполнить проверку на сервере, вы не можете предположим, что объекты, которые вы вернете, будут проверены.

Мое предложение было бы создать DTO из ваших объектов домена для отправки по проводам, которые не содержат никакой проверки, они просто простые сумки для хранения данных. Затем создайте фабрики, чтобы превратить ваши объекты домена в DTO и DTO в клиентские объекты. Фабрика просто берет DTO и передает члены в конструктор объекта домена. Тогда ваша логика проверки может жить в конструкторе объекта домена, где он принадлежит. При подходе, который у вас есть в настоящее время, вы, вероятно, в конечном итоге слегка скручиваете проверку, чтобы это можно было сделать как из конструктора, так и из метода [OnDeserialized].

Смежные вопросы