WCF-создание экземпляра объекта в конструкторе DataContract

у меня есть два класса, как показано ниже:

[DataContract]
public class Address
{
   [DataMember]
   public string Line1
   [DataMember]   
   public string Line2
   [DataMember]
   public string City
   [DataMember]
   public string State
   [DataMember]
   public string Zip
}

[DataContract]
public class Customer
{
   public Customer()
   {
      CustomerAddress = new Address();
   }

   [DataMember]
   public string FirstName
   [DataMember]
   public string LastName
   [DataMember]
   public Address CustomerAddress
}

что произойдет,если я создам прокси-сервер моего сервиса, который использует класс Customer? Если я правильно понимаю концепцию, я думаю, что конструктор в классе Customer не будет вызываться на стороне клиента, и он может дать другое поведение.

Как избавиться от этого конструктора в классе Customer и по-прежнему иметь CustomerAddress свойство типа Address Так что он ведет себя как тупой объект DTO?

каково общее руководство или лучшие практики, которые люди используют, чтобы избежать этой ситуации?

3 ответов


если вы используете значение по умолчанию DataContractSerializer чтобы сериализовать ваши объекты, тогда да, ваш конструктор не сериализуется, и любая логика, которую вы можете иметь в нем, не будет вызываться вашим клиентом при десериализации объекта.

Что касается вашего вопроса об удалении логики конструктора и наличии вложенного Address класс будет заполнен, о котором позаботится DataContractSerializer. Если у меня есть такой код:

Customer c = new Customer() { 
  FirstName = "David",
  LastName = "Hoerster",
  CustomerAddress = new Address() {
    Line1 = "1 Main Street",
    City = "Smallville",
    State = "AA",
    Zip = "12345"
  }
};

а затем верните это из метода службы, который Customer объект будет сериализован должным образом вместе с Address информация. Прокси-сервер на генерируемом клиенте будет знать о Address и сможет десериализовать поток, поступающий из метода службы, чтобы правильно построить ваш статья MSDN о сериализации WCF, где он говорит о DataContractSerializer.


если вы создать клиент (используя svcutil или "добавить ссылку на службу"), то сгенерированный DataContract будет выглядеть так:

[DataContract]
public class Customer
{
   // empty default constructor
   public Customer()
   {
   }

   [DataMember]
   public string FirstName
   [DataMember]
   public string LastName
   [DataMember]
   public Address CustomerAddress
}

ваши детали реализации не переносятся. Все, что генерируется, это то, что входит в WSDL, который является просто [DataMember] свойства в этом случае.

я упоминаю об этом потому, что ваш исходный вопрос спрашивает: "что произойдет, если я создам прокси".


если это объект отправляется с сервера клиенту, то вы всегда можете инициализировать CustomerAddress перед отправкой его клиенту. Infact, если ваш исходный код находится на сервере, то этот конструктор будет запущен, и WCF сериализует CustomerAddress и в основном никогда не отправляйте null (если вы не установите его обратно в null после конструктора).

если вы хотите сделать так, чтобы клиент всегда посылает вам CustomerAddress, то можно:

  • есть сервер проверьте значение null, например if(x.CustomerAddress == null) x.CustomerAddress = new Address();
  • отметьте элемент DataMember как требуется, тогда сервер вернет ошибку, если клиент ничего не передал:[DataMember(IsRequired=true)] public Address CustomerAddress;

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


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