Какой смысл DataContract в WCF?
VS.net создает шаблон при создании проекта WCF.
Он добавляет класс в файл iService1.cs:
// Use a data contract as illustrated in the sample below to
// add composite types to service operations.
[DataContract]
public class CompositeType
{
bool boolValue = true;
string stringValue = "Hello ";
[DataMember]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}
[DataMember]
public string StringValue
{
get { return stringValue; }
set { stringValue = value; }
}
}
Так как служба WCF может возвращать любой пользовательский класс, зачем использовать класс DataContract и CompositeType?
Я могу вернуть что-то вроде:
[OperationContract]
MyUserCollection GetUsers();
Что мне не хватает?
Ответы
Ответ 1
DataContract - это просто формальное определение типа, которое может быть понято с обеих сторон границы обслуживания.
Если вы вернетесь, как и в вашем примере, к объекту "MyUserCollection", потребители вашей службы должны будут ссылаться на внутренности вашего сервиса/системы, что является нарушением принципа SOA с явными границами. Используя DataContract, вы произвольно публикуете структуру возвращаемых типов.
Ответ 2
Еще одна интересная вещь, которую можно заметить: если вы украшаете свой код DataContract, у вас есть большой контроль над тем, что клиент может видеть и должен отправить обратно на ваш сервис. Например:
[DataContract]
public class SampleClass
{
[DataMember(IsRequired=true)]
public int MyRequiredProperty { get; set; }
[DataMember]
public int MyOptionalProperty { get; set; }
public int MyInternalProperty { get; set; }
}
В приведенном выше примере вы определили, что при получении данных вы ДОЛЖНЫ иметь MyRequiredProperty, и вы можете иметь или не MyOptionalProperty. Кроме того, клиент никогда не увидит MyInternalProperty (это может быть, например, какое-то свойство, которое помогает вашей логике внутренне, но вы не хотите, чтобы оно отображалось на уровне клиента).
Ответ 3
Существует еще одно важное использование, вы можете изменить Имя класса и свойств. Это удобная функция при сериализации и десериализации.
[DataContract(Name="EmployeeName")]
public class Person
{
[DataMember(Name="FullName")]
public string Name { get; set; }
[DataMember(Name="HomeAddress")]
public string Address { get; set; }
}
Ответ 4
Я не согласен с плакатом, который сказал: "DataContract - это просто формальное определение типа, которое можно понять по обе стороны границы службы".
Ключевое слово здесь - "type". В .NET тип - это объект, который может иметь поля, свойства и методы. Однако, когда вы украшаете класс DataContract
в своей службе WCF, результатом является не класс, магически пересаженный в вызывающий код; отнюдь не! В вызывающем коде у вас будет класс "прокси". Класс proxy получает XML, который представляет содержимое контракта данных. Вызывающий код может принимать эти значения XML через прокси-класс, но он не дает коду доступа к внутренним свойствам класса, украшенному DataContract
.
Ответ 5
Для ответа на "marc_s":
"Если у вас есть .NET на обоих концах провод, это просто отлично. Что, если вы иметь Java-клиент, вызывающий ваш оказание услуг? Если вы поместите свои данные внутрь DataContracts, эта информация получает хранятся в метаданных WSDL/XSD и могут использоваться клиентами, отличными от .NET тоже."
Я думаю, что это неверно. Попробуйте сделать это:
- Использовать пример WCF по умолчанию
проект с классом с
Атрибуты DataContract для классов
и DataMember для членов, а также
метод, который возвращает этот тип.
- Создайте его и покажите wsdl. Xsd содержит определение CompositeType. OK.
- Теперь удалите все атрибуты DataContract и DataMember
- Создайте его и покажите wsdl. Xsd все еще содержит определение ComposityType! (это более очевидно с помощью SCM soft, который не показывает разницы между файлами между шагами 2 и 4).
Таким образом, клиент Java должен управлять этим, без DataContract и DataMember! Я не прав или что?
Ответ 6
Возможно, не часто используется, мы могли бы использовать [DataContract] для прохождения через частные переменные. DataContractSerializer будет сериализовать/десериализовать только общедоступные типы, если атрибут [DataContract] не используется.
[DataContract]
public class SampleClass
{
[DataMember]
private int MyPrivateProperty { get; set; }
}
(Примечание. Если вы создаете прокси-сервер, тогда частные члены отображаются как общедоступные).