wcf引用未正确生成

时间:2011-10-28 14:54:44

标签: vb.net wcf

今天早上我的WCF引用遇到了一个奇怪的问题。简而言之,我设置了双工服务,以便服务器可以通过在数据协定中发送对象来通知客户端。当客户端连接时,它在服务器上运行一个函数,根据服务类的共享队列中的内容返回List(Of NewItem)。问题是,当我在客户端更新我的服务引用时,它说该函数返回一个NewItem对象,而不是List(Of NewItem)对象。我可以进入参考并手动将其更改为List对象,它将转移得很好。任何想法为什么服务引用生成器会随意更改我的返回类型?

以下是相关代码:

<ServiceContract(
    CallbackContract:=GetType(INotifyCallback),
    SessionMode:=ServiceModel.SessionMode.Required)>
Public Interface INotifyService
    <OperationContract()>
    Function GetNewServerItems() As List(Of NewItem)
End Interface

<DataContract>
<Serializable>
Public Class NewItem
    <DataMember()>
    Public Property ItemNum As String

    <DataMember()>
    Public Property Timestamp As DateTime
End Class

<ServiceBehavior(
    ConcurrencyMode:=ServiceModel.ConcurrencyMode.Single,
    InstanceContextMode:=ServiceModel.InstanceContextMode.Single)>
Public Class NotifyService
    Implements INotifyService

    Shared _server_items As New List(Of NewItem)

    Public Function GetNewServerItems() As List(Of NewItem)
        Return _server_items
    End Function
End Class

在Reference.vb(简化)中:

<System.ServiceModel.OperationContractAttribute(Action:="http://tempuri.org/INotifyService/GetNewServerItems", ReplyAction:="http://tempuri.org/INotifyService/GetNewServerItemsResponse")>  _
Function GetNewServerItems() As NotifyGateway.NewItem()

3 个答案:

答案 0 :(得分:3)

你和我陷入了同样的陷阱:我们都误读了为代理方法生成的VB.NET代码,因为它返回了一个项目。实际上,它正在返回一个数组。

WSDL使用XML Schema来描述请求和响应的形状。 XML Schema没有“list”的概念,只有序列的概念。默认情况下,当它看到一系列项目时,“添加服务引用”会生成一个数组。您可以通过更改“添加服务引用”或“配置服务引用”对话框的“高级”选项卡上的集合类型来更改此项以生成“列表”。

答案 1 :(得分:1)

以您的方式添加引用时,应将“高级服务引用设置”(“添加服务引用”对话框)中的“集合类型”更改为“system.Collections.Generic.List”。默认情况下,它是“System.Array”。

我不建议使用Add Reference方式,因为你失去了对WCF服务配置的控制,并且VS增加了很多你不需要的垃圾,这会使你的客户/服务链接更难维护

希望这有帮助。

答案 2 :(得分:1)

还有另一种不太知名但功能更强大的机制,用于保留集合类型而无需使用默认集合类型设置。

如果您在WCF管道两侧的代码中使用CollectionDataContract类,则此机制特别有用。

该解决方案涉及编辑作为WCF服务引用的一部分生成的svcmap,并为要序列化的每种集合类型添加特定的CollectionMapping条目。这里需要注意的主要问题是泛型:如果WCF找到给定类的多个匹配项,它将拒绝生成代码。

要实际进行更改:

1)显示项目中包含WCF服务引用的所有文件。

2)扩展您的服务参考

3)双击Reference.svmap文件进行编辑。

4)在CollectionMappings部分添加您的条目​​(如果它不存在,您可以添加它)。

例如,为了传输通用词典和列表,以及传输StringCollections,您可以输入以下条目:

<CollectionMappings>
  <CollectionMapping TypeName="System.Collections.Generic.Dictionary`2" Category="Dictionary" />
  <CollectionMapping TypeName="System.Collections.Generic.List`1" Category="List" />
  <CollectionMapping TypeName="System.Collections.Specialized.StringCollection" Category="List" />
<CollectionMappings>

带有Dictionary类别的第一个项目将作为默认的Dictionary集合类型,具有List类别的第一个项目将作为默认的Collection类型。

我们有超过200个集合类,我们以这种方式为Silverlight和Windows Forms客户端使用它,这是在WCF管道的两端重用自己的代码的一种非常有效的方法。

一个重要注意事项:要重用您的类,您需要确保检查服务引用配置中的“重用引用程序集中的类型”标志,或者确保reference.svmap中的GenerateInternalTypes标志设置为false(这些是一回事。)