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 инициализировать это поле для вас.
вам лучше определить все классы контрактов данных в сборке и иметь как серверный проект, так и клиентский проект ссылки на сборку, чтобы поведение инициализации можно было совместно использовать. При создании ссылки на службу можно указать генератору кода использовать существующие классы контрактов данных.