在WCF中实例化一个类

时间:2012-12-19 10:47:45

标签: asp.net vb.net wcf webmethod

我正在编写一个WCF WebMethod来上传文件,我从网上获取了一些片段。 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)

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

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

2 个答案:

答案 0 :(得分:2)

使用&#34;添加服务参考&#34;为您的服务创建代理时对话框,默认情况下,代理创建代码将&#34;展开&#34;消息合同,就像你拥有的那样。如果您希望邮件合同按照您在代理服务器端定义的那样显示,则需要选择&#34; Advanced&#34;选项卡,然后选中&#34;始终生成邮件合同&#34;选项。有了它,您也可以在您的客户端获得消息合同。

答案 1 :(得分:1)

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

MSDN中的Using Messaging Contracts文章包含了对消息传递合同可以做些什么的非常详细的描述,我怀疑微软选择了这种默认行为,因为你可以使用这些消息来播放一些“游戏”

但是,如果你在客户端检查为UploadFile生成的代码,那么有一些有趣的花絮可以帮助解释发生了什么。

第一个是界面中UploadFile方法的注释:

    '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)从MessageContract类中删除RemoteFileInfo属性。

2)虽然它看似违反直觉,但您可以查看Configure Service Reference Dialog Box中的Always generate message contracts复选框。