【问题标题】:Instantiating a class within WCF在 WCF 中实例化一个类
【发布时间】:2012-12-19 10:47:44
【问题描述】:

我正在编写一个 WCF WebMethod 来将文件上传到其中,我从网络上获取了 sn-ps。 WCF 界面如下所示:

<ServiceContract()>
Public Interface ITransferService

    <OperationContract()>
    Sub UploadFile(ByVal request As RemoteFileInfo)

End Interface

<MessageContract()>
Public Class RemoteFileInfo
    Implements IDisposable

    <MessageHeader(MustUnderstand:=True)>
    Public FileName As String

    <MessageHeader(MustUnderstand:=True)>
    Public Length As Long

    <MessageBodyMember(Order:=1)>
    Public FileByteStream As System.IO.Stream

    Public Sub Dispose() Implements IDisposable.Dispose
        If FileByteStream IsNot Nothing Then
            FileByteStream.Close()
            FileByteStream = Nothing
        End If
    End Sub

End Class

在 ASP.NET 中,当使用 web 方法时,由于某种原因,它仅在将接口用作RemoteFileInfo 的实例化的一部分时才有效:

Protected Sub btn_Click(sender As Object, e As EventArgs) Handles btn.Click
    If fu.HasFile Then
        Dim fi As New System.IO.FileInfo(fu.PostedFile.FileName)

        ' this is the line in question --------------
        Dim cu As ServiceReference1.ITransferService = New ServiceReference1.TransferServiceClient()
        ' -------------------------------------------

        Dim uri As New ServiceReference1.RemoteFileInfo()
        Using stream As New System.IO.FileStream(fu.PostedFile.FileName, IO.FileMode.Open, IO.FileAccess.Read)
            uri.FileName = fu.FileName
            uri.Length = fi.Length
            uri.FileByteStream = stream
            cu.UploadFile(uri)
        End Using
    End If
End Sub

谁能告知为什么不能使用以下方法创建TransferService 的实例:

Dim cu As New ServiceReference1.TransferServiceClient()

如果我尝试上述方法,它会打破这一行:

cu.UploadFile(uri)

...并且 UploadFile 必须使用三个参数(FileName、Length、FileByteStream)调用,即使没有使用此签名的方法。

请问在创建这个类的实例时为什么需要接口?

【问题讨论】:

    标签: asp.net vb.net wcf webmethod


    【解决方案1】:

    当您使用“添加服务引用”对话框为您的服务创建代理时,默认情况下,代理创建代码将“解包”消息合同,就像您拥有的那样。如果您希望消息合同按照您在代理服务器端的定义显示,您需要选择“高级”选项卡,并选中“始终生成消息合同”选项。这样,您也将在客户端中获得消息合同。

    【讨论】:

      【解决方案2】:

      问题在于,当遇到 MessageContract 作为参数时,WCF 客户端生成默认情况下假定您要实现消息传递样式的接口,并提供消息协定中的离散属性作为客户端的一部分侧接口。

      MSDN 中的Using Messaging Contracts 文章非常详细地描述了可以使用消息传递合同完成的操作,我怀疑 Microsoft 之所以选择这种默认行为是因为您可以使用这些消息玩一些“游戏”。

      但是,如果您在客户端检查为 UploadFile 生成的代码,就会发现一些有趣的花絮有助于解释正在发生的事情。

      首先是接口中UploadFile方法的cmets:

          'CODEGEN: Generating message contract since the operation UploadFile is neither RPC nor document wrapped.
          ...
          Function UploadFile(ByVal request As ServiceReference1.RemoteFileInfo) As ServiceReference1.UploadFileResponse
      

      这意味着如果消息合约有不同的实现,合约的生成方式也会不同。

      第二个是您将看到用于实际进行服务调用的代码并没有什么特别之处:

          Public Sub UploadFile(ByVal FileName As String, ByVal Length As Long, ByVal FileByteStream As System.IO.Stream)
              Dim inValue As ServiceReference1.RemoteFileInfo = New ServiceReference1.RemoteFileInfo()
              inValue.FileName = FileName
              inValue.Length = Length
              inValue.FileByteStream = FileByteStream
              Dim retVal As ServiceReference1.UploadFileResponse = CType(Me,ServiceReference1.ITransferService).UploadFile(inValue)
          End Sub
      

      所以在这种情况下,您的代码所做的正是生成的代码所做的。但是,如果 MessageContract 更复杂,我怀疑情况将不再如此。

      所以,对于你的问题:

      谁能告诉我为什么不能创建一个实例 TransferService 使用如下方式...

      只要您验证方法调用的实现与您的代码功能等效,就没有理由不采用这种方法。

      有几个选项可以更改客户端中方法的默认生成:

      1) 从RemoteFileInfo 类中删除MessageContract 属性。

      2) 虽然看起来有违直觉,但您可以勾选Configure Service Reference Dialog Box 中的Always generate message contracts 复选框。

      【讨论】:

      • 哇 - 惊人的答案 - 谢谢!关于您的评论: >> 从 RemoteFileInfo 类中删除 MessageContract 属性 我是否需要用 DataContractAttribute 替换它?另外,请您详细说明可以玩哪些“游戏”?作为 WCF 的新手,我想得到任何额外的建议,即使这意味着更多的阅读......!再次感谢
      • Re RemoteFileInfo:是的,使用 DataContract 将是最佳实践,尽管它不是严格要求,因为 WCF 将自动处理普通旧类对象 (POCO)。 re Games:我主要指的是您可以操作底层 SOAP 消息的大量方法(加密部分、具有不同的命名空间、使用不同的序列化引擎等),这些方法可能会对客户端生成的数据产生影响,也可能不会代码(有关各种功能的深入讨论,请参阅 MSDN 文章)。
      • 超级。非常感谢您的详细回复。
      • 只是在读一本关于 WCF 4 的书。为了补充您的答案,DataContract 不能与任何类型的 Stream 对象一起使用,而 MessageContract 必须与 Streams 一起使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多