Как вы возвращаете определенный пользователем тип из службы WCF? - PullRequest
7 голосов
/ 13 января 2009

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

Ответы [ 4 ]

10 голосов
/ 13 января 2009

Если тип, который вы хотите вернуть из вызова службы, не помечен как 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. 1016 *

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

4 голосов
/ 13 января 2009

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

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

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

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

4 голосов
/ 13 января 2009

С точностью до секунды мысли Йосси / мысли Рича :

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

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

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

4 голосов
/ 13 января 2009

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

...