WCF - Общий список (из T) - PullRequest
       34

WCF - Общий список (из T)

1 голос
/ 09 октября 2009

У меня есть список пользовательских DTO, которые я пытаюсь передать службе WCF.

Я получаю следующую ошибку:

Произошла ошибка при попытке сериализации параметра tcp: // localhost /: oObject. Сообщение InnerException было «Type» System.Collections.Generic.List`1 [[TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat.HeartBeatDTO, WFCommon, Version = 1.0.0.0, Culture = нейтральный, PublicKeyToken = null]] 'с данными имя контракта 'ArrayOfHeartBeatDTO: TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat' не ожидается. Добавьте любые типы, которые не известны статически, в список известных типов - например, с помощью атрибута KnownTypeAttribute или добавив их в список известных типов, переданных в DataContractSerializer. '. Пожалуйста, смотрите InnerException для более подробной информации.

У меня установлены DTO DataContract и DataMember. Я сделал ссылку на службу автоматического WCF и убедился, что у меня есть расширенные опции, чтобы изменить коллекции на общие списки вместо массива.

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

Код отправителя:

<DataContract(Name:="HeartBeatDTO", Namespace:="TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat")> _
Public Class HeartBeatDTO

Public Sub IssuePatientReport()
  SBClient.SendCommunication(_PatientID, _HeartBeats)
End Sub

Код на приемнике:

Public Sub SendCommunication(ByVal sKey As String, ByVal oObject As Object) Implements iOperatorCommunication.SendCommunication
        If _CurrentCommunicationLog.ContainsKey(sKey) Then
            _CurrentCommunicationLog.Item(sKey) = oObject
        Else
            _CurrentCommunicationLog.Add(sKey, oObject)
        End If
    End Sub

Мой интерфейс:

<ServiceContract(Namespace:="tcp://localhost/")> _
<ServiceKnownType(GetType(List(Of HeartBeatDTO)))> _
Public Interface iOperatorCommunication
    <OperationContract()> _
    Function ReceiveCommunication(ByVal sKey As String) As Object

    <OperationContract()> _
    Function ReturnCommunicationLevel() As Integer

    <OperationContract()> _
    Function ReturnCommunications() As Dictionary(Of String, Object)

    <OperationContract()> _
    Function ReturnCommunicationsByKeySearch(ByVal sSearch As String) As Dictionary(Of String, Object)

    <OperationContract()> _
    Sub SendCommunication(ByVal sKey As String, ByVal oObject As Object)
End Interface

UPDATE: Вот новое сообщение об ошибке:

Произошла ошибка при попытке параметр сериализации TCP: // локальный /: oObject. Сообщение InnerException было «Тип 'TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat.HeartBeatDTOList' с названием контракта данных 'HeartBeatDTOList: TEGE.ER.WorkFlowEngine.WFCommon.HeartBeat' не ожидается Добавить любые типы не статически известен к списку известных типы - например, с помощью Атрибут KnownTypeAttribute или добавив их в список известных типов передано в DataContractSerializer. '. Пожалуйста, смотрите InnerException для более подробности.

1 Ответ

6 голосов
/ 09 октября 2009

Если у вас есть пользовательские типы коллекций, вам может потребоваться украсить их специальным атрибутом - см. Документы MSDN по CollectionDataContract :

[CollectionDataContract] 
public class CustomerList2 : Collection<string> {}

Может ли это быть проблемой?


ОБНОВЛЕНИЕ: хорошо, спасибо за публикацию интерфейса. Я не эксперт по VB.NET, но из того, что я понимаю и вижу, вы никогда не используете тип «HeartbeatDTO» ни в одном из ваших методов, украшенных атрибутом OperationContract - верно?

Так что я думаю, вы, вероятно, также должны определить это как «ServiceKnownType» - попробуйте это:

<ServiceContract(Namespace:="tcp://localhost/")> _
<ServiceKnownType(GetType(HeartBeatDTO))> _
<ServiceKnownType(GetType(List(Of HeartBeatDTO)))> _
Public Interface iOperatorCommunication

Это помогает?

Также: есть ли какая-то особая причина, по которой вы используете «Объект» в качестве типа в контракте на обслуживание? Не могли бы вы указать HeartbeatDTO или List(Of HeartbeatDTO)?

ОБНОВЛЕНИЕ: не могли бы вы попытаться - просто ради того, чтобы посмотреть, работает ли он - создать новый список интерфейсов сервисов так:

<ServiceContract(Namespace:="tcp://localhost/")> _
Public Interface iOperatorCommunicationStripped
    <OperationContract()> _
    Sub SendCommunication(ByVal sKey As String, ByVal oObject As List(Of HeartbeatDTO))
End Interface

В этом случае ваша служебная операция явно относится к своему типу данных и использует список объектов HeartbeatDTO, которые определены как контракты данных. Если вы знаете, создаете клиентский прокси для этого контракта на обслуживание и вызываете метод - это работает ??

Марк

...