Подтвердить что ты не робот

Какой смысл 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();

Что мне не хватает?

4b9b3361

Ответ 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; }
}

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