В WCF могут ли классы контрактов данных наследовать друг от друга? - PullRequest
24 голосов
/ 04 февраля 2009

В службе WCF у меня есть два класса с атрибутом [DataContract]. Один из этих классов имеет отношение «is-a» с другим, поэтому класс B может наследовать от класса A. Однако, когда я настраиваю наследование между этими двумя классами, оба из которых обозначены атрибутом [DataContract], метаданные не загружаются при тестировании сервисов.

Возможно ли это в WCF? Я пропускаю другой атрибут?

[DataContract]
public class A
{        
    [DataMember]
    public MyCustomType AValue1{ get; set; }

    [DataMember]
    public MyCustomType AValue2 { get; set; }
}

[DataContract]
public class B: A
{       
   [DataMember]
   public double BValue1{ get; set; }

   [DataMember]
   public double BValue2 { get; set; }
}

ПРИМЕЧАНИЕ. Пользовательские типы также определяются с использованием контрактов данных.

ОБНОВЛЕНИЕ : Ниже приведена ошибка:

Ошибка: невозможно получить метаданные из http://localhost:8002/GISDataServices/mex Если это служба Windows (R) Communication Foundation, к которой у вас есть доступ, убедитесь, что вы включили публикацию метаданных по указанному адресу. Для получения справки о включении публикации метаданных см. Документацию MSDN по адресу http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata URI ошибки Exchange: http://localhost:8002/GISDataServices/mex Метаданные содержат ссылку, которую невозможно разрешить: 'http://localhost:8002/GISDataServices/mex'. Receivera:InternalServiceFault Сервер не удалось обработать запрос из-за внутренней ошибки. Для получения дополнительной информации об ошибке либо включите IncludeExceptionDetailInFaults (либо из ServiceBehaviorAttribute, либо из поведения конфигурации ) на сервере, чтобы отправить информацию об исключении обратно клиенту, либо включите трассировку в соответствии с Microsoft .NET Framework 3.0 Документация SDK и проверка журналов трассировки сервера. HTT GET Ошибка URI: http://localhost:8002/GISDataServices/mex Произошла ошибка при загрузке 'http://localhost:8002/GISDataServices/mex'. Запрос не выполнен с состоянием HTTP 400: Bad Request.

ОБНОВЛЕНИЕ 2: См. Мой ответ ниже.

Ответы [ 3 ]

39 голосов
/ 04 февраля 2009

Да, но вам нужно украсить базовый класс с помощью [KnownTypeAttribute], создав его с типом производного класса. Например:

[DataContract]
[KnownType(typeof(B))]
public class A
{
   [DataMember]
   public string Value { get; set; }
}

[DataContract]
public class B : A
{
   [DataMember]
   public string OtherValue { get; set; }
}
7 голосов
/ 04 февраля 2009

Хорошо, я разобрался с вопросом. Ответ ... я идиот. Это не имеет ничего общего с наследством. В базовом классе у меня был член контракта данных без условия свойства 'set' - только 'get'. Doh !!! Вставка предложения 'set' заставила его работать как шарм.

Извините за путаницу.

1 голос
/ 04 февраля 2009

На основании этого теста он должен работать нормально. У обоих классов есть Конструкторы по умолчанию? Вы используете Авто-Свойства. Примечание. В этом базовом примере атрибуты не требуются. Кроме того, как отметил Дэвид Мортон, в зависимости от того, какой элемент вы возвращаете, вам может понадобиться атрибут KnownType, я не на 100%, но известный тип, возможно, должен идти в операционном контракте.

class Program
{
    static void Main(string[] args)
    {
        var serializer = new DataContractSerializer(typeof(Employee));

        var employee = new Employee() { Name="Joe", Salary=100000  };
        using (var ms = new MemoryStream())
        {
            serializer.WriteObject(ms, employee);

            ms.Position = 0;

            var newEmployee = serializer.ReadObject(ms) as Employee;
        }

        Console.ReadKey();

    }
}

[DataContract]
public class Employee : Person
{
    [DataMember]
    public decimal Salary { get; set; }
}

[DataContract]
public class Person
{
    [DataMember]
    public string Name { get; set; }
}

[ServiceContract]
interface IEmployeeService
{
    [OperationContract]
    Person GetPerson();

    [OperationContract]
    Employee GetEmployee();

    [OperationContract]
    [KnownType(typeof(Employee))]
    Person GetEmployeeAsPerson();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...