Нужно лучшее руководство, чтобы изменить контракт на обслуживание WCF позже
Я новичок, но читая какую-то статью о wcf, я узнал, что если я изменю ServcieContrcat
тогда я должен изменить не только конец службы, но и конец клиентов, и это действительно трудно управлять.
Example 1:
Разработчик должен создать сервис WCF для обработки заказов со следующей функцией: GetOrderById, GetOrdersByStatus, SaveOrder
ServiceContract может выглядеть следующим образом
[ServiceContract]
public interface IOrderService
{
[OperationContract]
Order GetOrderById(int orderId);
[OperationContract]
List<Order> GetOrdersByStatus(OrderStatus orderStatus);
[OperationContract]
void SaveOrder(Order order)
}
например, через несколько месяцев руководитель проекта скажет: "Хорошо, нашим клиентам нужны другие функции: DeleteOrderById, GetOrdersByCustomerId
и не нужно GetOrdersByStatus
больше нам нужно GetOrdersByStatusAndCustomerId
Разработчики должны обновить ServiceContrcat
и обновить клиент. Как видите, любые изменения в ServiceContrcat
действительно сложно
поэтому я ищу лучшее руководство по разработке службы wcf, которая не создаст никаких проблем, если мы расширим функциональность или внесем какие-либо изменения, но клиентская часть не столкнется с какой-либо проблемой Спасибо
один парень отвечал раньше за ту же ситуацию
Это то, что я сделал: все мои 30+ функций (и список растет и растет) принимали строки, целые и байты () в качестве типов данных как входные и выходные параметры, я создал единую главную конечную точку и функцию, которая получает, как входной параметр и отправляет обратно в качестве вывода, один простой класс. Этот класс, называемый HostInterface, содержит всего два параметра: строку (которую я использую для инкапсуляции всех моих строк и целых) и массив byte() (в который я вставляю все свои двоичные файлы)
Таким образом, независимо от того, вызывает ли клиент что-то простое, например, Ping() с одним строковым параметром, или что-то сложное, например, ResumeDownload() с 5 строками, 2 int и байтовым массивом, все эти параметры инкапсулируются в моем классе HostInterface, в строках. и вставляет в один параметр String (как XML), а байты - в поле байтов.
Я ценю его ответ, но на самом деле не понимаю, как его реализовать. так что, если кто-то перейдет по этому URL-адресу Как изменить контракт на обслуживание WCF, который не влияет на клиента?
тогда знает, что он сказал.
я ищу небольшой полный код сервиса wcf, который поможет мне визуализировать, как составить контракт на обслуживание таким образом, чтобы, если мы позже расширим функциональность контракта на обслуживание, клиент, который будет использовать мой сервис, не столкнулся бы с какой-либо проблемой
и скажите мне другую возможную линию, чтобы решить эту ситуацию. Спасибо
2 ответа
Я думаю, что предложение о создании общей конечной точки является плохой идеей. Создав метод, который принимает любые данные, вы потеряли все преимущества строгой типизации, которые дает вам WCF в C#. Вы все еще должны выполнить тяжелую работу со старыми клиентами, но теперь вы должны сделать это в коде приложения, проверяя поступающие данные и эвристически решая, какую "версию" он принимает. На мой взгляд, это похоже на создание одной таблицы базы данных SQL с десятками столбцов с именем id
, data1
, data2
, data3
, data4
и т. д., затем сохраняя все виды несвязанных данных в этой одной таблице.
Если необходимые вам изменения в договоре обратно совместимы, вы можете добавить их в договор на месте. Добавление нового метода обратно совместимо, так как оно не влияет на доступность существующих методов.
Если вам необходимо внести обратно несовместимые изменения (например, удалить метод или изменить параметры существующего), самый простой ответ может заключаться в создании нового контракта, который живет по новому адресу. Если версия 1 вашего договора достигнута по адресу http://example.com/v1/MyService, то версия 2 доступна по адресу http://example.com/v2/MyService.
Чтобы избежать дублирования большого количества кода между классами, где контракт не сильно изменился, классы, реализующие контракты, могут наследоваться друг от друга. Один из способов сделать это может быть:
namespace V1
{
[ServiceContract]
public interface IService { ... }
public class MyService : IService { ... }
}
namespace V2
{
[ServiceContract]
public interface INewService { ... }
public class MyNewService : V1.MyService, INewService { ... }
}
Или вы можете использовать композицию:
public class MyNewService : INewService
{
private readonly V1.MyService v1service = new V1.MyService();
public int SomeMethod()
{
return this.v1service.SomeMethod();
}
}
Сюда, MyNewService
реализует всю функциональность MyService
, но только методы, представленные INewService
будет доступен через WCF. Любой, кто получит доступ к вашему сервису через v2 URL, получит новую функциональность. Клиенты, которые используют старую службу, будут продолжать использовать URL-адрес v1, пока не будут готовы к обновлению.
Если я правильно понимаю вашу проблему, то, вероятно, вам поможет класс ChannelFactory (по крайней мере, частично). Ссылка здесь поможет вам начать.
Также вы можете использовать IExtensibleDataObject для прямой совместимости. Проверьте ссылку здесь для лучшего понимания.
Надеюсь это поможет.