Добавление поля к контракту данных WCF нарушает клиентов?

У меня есть служба WCF, которая возвращает класс, который реализует IExtensibleDataObject. Мне нужно добавить новое поле в этот класс. Я обновил интерфейс DataContract и внес изменения в класс. Теперь, когда я пытаюсь запустить клиентское приложение, я получаю следующую ошибку:

Не удалось загрузить файл или сборку 'xxx.yyyy.zzzz, Version = 1.3.9.26111, Culture = нейтрально, PublicKeyToken = b09e2f3e9b5894f0 'или одной из его зависимостей. Расположенные определение манифеста сборки не соответствуют ссылочной позиции сборки. (Исключение из HRESULT: 0x80131040)

Изменена команда AssemblyVersion класса WFC - это разрывает клиент?

EDIT:

Есть клиенты в производстве, которые используют эту услугу. Я не хочу, чтобы они обновляли свою служебную ссылку и повторно развертывали своих клиентов для этого простого изменения, если это возможно.

Ответы

Ответ 1

Это зависит от того, как вы установили свой контракт с данными.

В WCF, используя все значения по умолчанию, ваша служба будет использовать DataContractSerializer (DCS) для сериализации вашего объекта в XML. DCS будет сериализовать ваши поля в порядке - сначала публичные, а затем частные. В каждой группе видимости он будет упорядочивать поля/свойства по алфавиту по имени.

Таким образом, если вы вводите новое публичное свойство MiddleName, и у вас уже есть FirstName и LastName, все будет хорошо: старый XML был бы

<YourObject>
   ....
   <FirstName>.....</FirstName>
   <LastName>.....</LastName>
</YourObject>

и ваш новый просто добавит новое свойство в конец:

<YourObject>
   ....
   <FirstName>.....</FirstName>
   <LastName>.....</LastName>
   <MiddleName>....</MiddleName>
</YourObject>

Такое обновление "добавить что-то в конце" должно работать нормально, DCS просто просто игнорирует дополнительные теги в XML.

Однако: если бы вы ввели свойство под названием Gender, которое было бы застряло между <FirstName> и <LastName> и таким образом нарушило бы порядок данных в вашем XML и, таким образом, сломало бы контракт с данными - никакой "старый" клиент не сможет вызвать вашу новую услугу.

Чтобы получить контроль над этим, вы можете поместить в свои данные конкретные атрибуты Order= в своих данных:

[DataContract]
public class SomeAddress
{
   [DataMember(Order=0)]
   public string FirstName;

   [DataMember(Order=1)]
   public string LastName;
}

Тогда вы можете легко добавить новое свойство - просто добавьте его в конец списка!

[DataContract]
public class SomeAddress
{
   [DataMember(Order=0)]
   public string FirstName;

   [DataMember(Order=1)]
   public string LastName;

   [DataMember(Order=2)]
   public string Gender;
}

Таким образом, используя атрибут Order= в ваших контрактах с данными, вы можете взять под свой контроль свой XML-макет, и вы можете сделать простые расширения существующих контрактов данных без прерывания обновлений.

Для получения дополнительной информации и углубленного ноу-хау вам следует прочитать Сериализация в Windows Communication Foundation на веб-сайте MSDN Magazine - настоятельно рекомендуется.