Как вы возвращаете определенный пользователем тип из службы WCF?

StackOverflow https://stackoverflow.com/questions/438669

Вопрос

У меня есть служба WCF, размещенная в IIS.Намерение состоит в том, чтобы клиенты совершили вызов и получили пользовательский класс, который определен в другом проекте / dll.Я сгенерировал клиент-службу, используя svcutil.exe.Проблема в том, что этот автоматически созданный клиент содержит новое частичное / прокси-определение для класса, который я пытаюсь вернуть из сервиса.Теперь он выдает ошибку преобразования между моим исходным пользовательским классом и новым частичным определением во время компиляции.Итак, как вы возвращаете пользовательские типы из службы WCF?Совет приветствуется.

Это было полезно?

Решение

Просто на секунду У Йоси/У Рича мысли:

  • да, вы можете добавить ссылку на общую библиотеку dll (вместо использования сгенерированного прокси-класса)
  • да, это противоречит многим целям контрактов с данными, и если происходит какая-либо пользовательская сериализация, у вас могут возникнуть проблемы с расширением вашего сервиса

Я уже ходил по этому пути раньше и в некотором смысле жалею, что сделал это.Повторная расширяемость / пользовательская сериализация - вы должны быть очень осторожнее.Немного проще, если вы используете предварительно свернутый сериализатор, такой как protobuf-сеть (который может интегрироваться непосредственно в WCF и который разработан с учетом расширяемости), но непростой.

На самом деле, один преимущество преимущество совместного использования классов заключается в том, что это немного упрощает тестирование:поскольку у вас есть то же самое IFoo везде вы можете насмехаться над этим IFoo с разумными шансами на успех.Сложнее имитировать, когда задействован прокси-сервер (поскольку вы меняете больше движущихся частей между тестовым кодом и производственным кодом).

Другие советы

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

using System;
using System.ServiceModel;

[ServiceContract]
interface IService
{
    [OperationContract]
    TimeSpan GetTimeSpan();
}

class Service : IService
{
    public TimeSpan GetTimeSpan() { return DateTime.Now.TimeOfDay; }
}

Почему тогда работает предыдущий код? Это работает, потому что обе стороны вызова службы имеют System.dll , поэтому они оба знают о типе System.TimeSpan , который является типом возврата OperationContract GetTimeSpan ( ) .

Вот пример использования DataContract :

using System;
using System.ServiceModel;
using System.Runtime.Serialization;

[ServiceContract]
interface IService
{
    [OperationContract]
    Contract GetContract();
}

[DataContract]
class Contract
{
    [DataMember]
    public String MyProperty { get; set; }
}

class Service : IService
{
    public Contract GetContract() { return new Contract(); }
}

Теперь вы предоставили атрибуты сериализации для определенного вами класса ( Contract ) - это позволит вам использовать svcutil.exe для создания прокси-классов в вашем клиентском приложении. это будет сериализовано и отправлено службе WCF.

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

Одна из вещей, которая должна произойти, состоит в том, что пользователь должен настроить ссылку на службу для использования ваших типов из DLL, а не класса, определенного прокси-сервером - http://msdn.microsoft.com/en-us/library/bb628653.aspx

В прошлом мы шли по этому пути, и, действительно, проблема в том, что, конечно, это два разных класса, поэтому вам придется перейти по ссылке, предоставленной @Rich Reuter;

Однако мы усвоили трудный путь, почему это плохая практика, поскольку она повторяет третий принцип SOA- " Схема общего доступа к службам и контракт, а не класс ".

Конечно, проблема заключается не просто в том, чтобы не следовать «правилу» установленный кем-то в какой-то момент, но для этого были веские причины - мы узнали, что цена такой жесткой связи между услугой и клиентом означает, что ее тоже очень трудно выпустить - если услугу нужно добавить другое поле для этого класса для обслуживания другого клиента - может быть затронут первый клиент; если службе необходимо что-то изменить в определении этого класса (для обслуживания другого клиента) - это повлияет на первого клиента, и наоборот - клиент может повлиять на жизненный цикл службы.

В крупных проектах это быстро становится огромным бременем обслуживания.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top